LCOV - code coverage report
Current view: top level - interp_2d/private - bicub_db.f (source / functions) Coverage Total Hit
Test: coverage.info Lines: 28.6 % 1132 324
Test Date: 2025-05-08 18:23:42 Functions: 47.1 % 17 8

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2012  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 bicub_db
      21              : 
      22              :       use const_def, only: dp
      23              : 
      24              :       !implicit none
      25              : 
      26              : 
      27              :       contains
      28              : 
      29              : !        from PSPLINE by Doug McCune (version as of February, 2004)
      30              : 
      31              : 
      32              : !        PSPLINE Home Page:
      33              : !        http://w3.pppl.gov/NTCC/PSPLINE
      34              : 
      35              : !        Doug McCune, Princeton University
      36              : !                dmccune@pppl.gov
      37              : 
      38              : 
      39              : !  bcspeval -- eval bicubic spline function and/or derivatives
      40              : 
      41            0 :       subroutine bcspeval_db(xget,yget,iselect,fval,x,nx,y,ny,ilinx,iliny,f,inf3,ier)
      42              : 
      43              :       implicit none
      44              :       integer iselect(6)
      45              :       integer ilinx,iliny,nx,ny,inf3,ier
      46              : 
      47              :       real(dp) xget,yget
      48              :       real(dp) fval(6)
      49              :       real(dp) x(nx),y(ny),f(4,4,inf3,ny)
      50              : 
      51              : !  modification -- dmc 11 Jan 1999 -- remove SAVE stmts;
      52              : !    break routine into these parts:
      53              : 
      54              : !    bcspevxy -- find grid cell of target pt.
      55              : !    bcspevfn -- evaluate function using output of bcpsevxy
      56              : 
      57              : !    in cases where multiple functions are defined on the same grid,
      58              : !    time can be saved by using bcspevxy once and then bcspevfn
      59              : !    multiple times.
      60              : 
      61              : !  input:
      62              : !     (xget,yget)   location where interpolated value is desired
      63              : !                   x(1) <= xget <= x(nx) expected
      64              : !                   y(1) <= yget <= y(ny) expected
      65              : 
      66              : !     iselect       select desired output
      67              : 
      68              : !                     iselect(1)=1 -- want function value (f) itself
      69              : !                     iselect(2)=1 -- want  df/dx
      70              : !                     iselect(3)=1 -- want  df/dy
      71              : !                     iselect(4)=1 -- want  d2f/dx2
      72              : !                     iselect(5)=1 -- want  d2f/dy2
      73              : !                     iselect(6)=1 -- want  d2f/dxdy
      74              : 
      75              : !              example:  iselect(1)=iselect(2)=iselect(3)=1
      76              : !                            f, df/dx, and df/dy all evaluated
      77              : !                        iselect(4)=iselect(5)=iselect(6)=0
      78              : !                            2nd derivatives not evaluated.
      79              : 
      80              : !                   the number of non zero values iselect(1:6)
      81              : !                   determines the number of outputs...
      82              : !                   see fval (output) description.
      83              : 
      84              : !  new dmc December 2005 -- access to higher derivatives (even if not
      85              : !  continuous-- but can only go up to 3rd derivatives on any one coordinate.
      86              : !     if iselect(1)=3 -- want 3rd derivatives
      87              : !          iselect(2)=1 for d3f/dx3
      88              : !          iselect(3)=1 for d3f/dx2dy
      89              : !          iselect(4)=1 for d3f/dxdy2
      90              : !          iselect(5)=1 for d3f/dy3
      91              : !               number of non-zero values iselect(2:5) gives no. of outputs
      92              : !     if iselect(1)=4 -- want 4th derivatives
      93              : !          iselect(2)=1 for d4f/dx3dy
      94              : !          iselect(3)=1 for d4f/dx2dy2
      95              : !          iselect(4)=1 for d4f/dxdy3
      96              : !               number of non-zero values iselect(2:4) gives no. of outputs
      97              : !     if iselect(1)=5 -- want 5th derivatives
      98              : !          iselect(2)=1 for d5f/dx3dy2
      99              : !          iselect(3)=1 for d5f/dx2dy3
     100              : !               number of non-zero values iselect(2:3) gives no. of outputs
     101              : !     if iselect(1)=6 -- want 6th derivatives
     102              : !          d6f/dx3dy3 -- one value is returned.
     103              : 
     104              : !     x(1...nx)     independent coordinate x, strict ascending
     105              : !     y(1...ny)     independent coordinate y, strict ascending
     106              : 
     107              : !     ilinx  --  =1: flag that x is linearly spaced (avoid search for speed)
     108              : !     iliny  --  =1: flag that y is linearly spaced (avoid search for speed)
     109              : 
     110              : !  **CAUTION** actual even spacing of x, y is NOT CHECKED HERE!
     111              : 
     112              : !
     113              : !     f             the function values (at grid points) and spline coefs
     114              : 
     115              : !  evaluation formula:  for point x btw x(i) and x(i+1), dx=x-x(i)
     116              : !                             and y btw y(j) and y(j+1), dy=y-y(j),
     117              : 
     118              : !      spline value =
     119              : !        f(1,1,i,j) + dx*f(2,1,i,j) + dx**2*f(3,1,i,j) + dx**3*f(4,1,i,j)
     120              : !   +dy*(f(1,2,i,j) + dx*f(2,2,i,j) + dx**2*f(3,2,i,j) + dx**3*f(4,2,i,j))
     121              : !   +d2*(f(1,3,i,j) + dx*f(2,3,i,j) + dx**2*f(3,3,i,j) + dx**3*f(4,3,i,j))
     122              : !   +d3*(f(1,4,i,j) + dx*f(2,4,i,j) + dx**2*f(3,4,i,j) + dx**3*f(4,4,i,j))
     123              : 
     124              : !      where d2=dy**2 and d3=dy**3.
     125              : 
     126              : !  output:
     127              : !      up to 6 elements of fval, ordered as follows:
     128              : !        fval(1)=function value or lowest order derivative requested
     129              : !        fval(2)=next order derivative
     130              : !             etc
     131              : !        the ordering is a subset of the sequence given under the "iselect"
     132              : !        description.
     133              : 
     134              : !      ier = 0 -- successful completion; = 1 -- an error occurred.
     135              : 
     136              : !-------------------------------------------------------------------
     137              : !  local
     138              : 
     139              :       integer :: i=0
     140              :       integer :: j=0
     141              : 
     142            0 :       real(dp) :: dx, dy
     143              : 
     144              : !--------------------------
     145              : 
     146              :       call bcspevxy_db(xget,yget,x,nx,y,ny,ilinx,iliny,
     147            0 :      &   i,j,dx,dy,ier)
     148            0 :       if(ier /= 0) return
     149              : 
     150              :       call bcspevfn_db(iselect,1,1,fval,(/i/),(/j/),
     151            0 :      &   (/dx/),(/dy/),f,inf3,ny)
     152              : 
     153            0 :       return
     154              :       end subroutine bcspeval_db
     155              : 
     156              : 
     157              : !-------------------------------------------------------------------------
     158              : !  bcspevxy -- look up x-y zone
     159              : 
     160              : !  this is the "first part" of bcspeval, see comments, above.
     161              : 
     162            0 :       subroutine bcspevxy_db(xget,yget,x,nx,y,ny,ilinx,iliny,
     163              :      &   i,j,dx,dy,ier)
     164              : 
     165              :       integer nx,ny                     ! array dimensions
     166              : 
     167              :       real(dp) xget,yget                    ! target point
     168              :       real(dp) x(nx),y(ny)                  ! indep. coords.
     169              : 
     170              :       integer ilinx                     ! =1:  assume x evenly spaced
     171              :       integer iliny                     ! =1:  assume y evenly spaced
     172              : 
     173              : !  output of bcspevxy
     174              : 
     175              :       integer i,j                       ! index to cell containing target pt
     176              :       real(dp) dx,dy                        ! displacement of target pt w/in cell
     177              :                                         ! dx=x-x(i)  dy=y-y(j)
     178              : 
     179              :       integer ier                       ! return ier /= 0 on error
     180              : 
     181              : !------------------------------------
     182              : 
     183              :       real(dp) zxget, zyget
     184            0 :       ier=0
     185              : 
     186              : !  range check
     187              : 
     188            0 :       zxget=xget
     189            0 :       zyget=yget
     190              : 
     191            0 :       if((xget < x(1)).or.(xget > x(nx))) then
     192            0 :          zxtol=4.0d-7*max(abs(x(1)),abs(x(nx)))
     193            0 :          if((xget < x(1)-zxtol).or.(xget > x(nx)+zxtol)) then
     194            0 :             ier=1
     195              : !            write(6,1001) xget,x(1),x(nx)
     196              : ! 1001       format(' ?bcspeval:  xget=',1pe11.4,' out of range ', 1pe11.4,' to ',1pe11.4)
     197              :          else
     198              : !            if((xget < x(1)-0.5*zxtol).or. (xget > x(nx)+0.5*zxtol)) write(6,1011) xget,x(1),x(nx)
     199              : ! 1011       format(' %bcspeval:  xget=',1pe15.8,' beyond range ', 1pe15.8,' to ',1pe15.8,' (fixup applied)')
     200            0 :             if(xget < x(1)) then
     201            0 :                zxget=x(1)
     202              :             else
     203            0 :                zxget=x(nx)
     204              :             end if
     205              :          end if
     206              :       end if
     207            0 :       if((yget < y(1)).or.(yget > y(ny))) then
     208            0 :          zytol=4.0d-7*max(abs(y(1)),abs(y(ny)))
     209            0 :          if((yget < y(1)-zytol).or.(yget > y(ny)+zytol)) then
     210            0 :             ier=1
     211              : !            write(6,1002) yget,y(1),y(ny)
     212              : ! 1002       format(' ?bcspeval:  yget=',1pe11.4,' out of range ', 1pe11.4,' to ',1pe11.4)
     213              :          else
     214              : !         if((yget < y(1)-0.5*zytol).or.(yget > y(ny)+0.5*zytol)) write(6,1012) yget,y(1),y(ny)
     215              : ! 1012       format(' %bcspeval:  yget=',1pe15.8,' beyond range ', 1pe15.8,' to ',1pe15.8,' (fixup applied)')
     216            0 :             if(yget < y(1)) then
     217            0 :                zyget=y(1)
     218              :             else
     219            0 :                zyget=y(ny)
     220              :             end if
     221              :          end if
     222              :       end if
     223            0 :       if(ier /= 0) return
     224              : 
     225              : !  now find interval in which target point lies..
     226              : 
     227            0 :       nxm=nx-1
     228            0 :       nym=ny-1
     229              : 
     230            0 :       if(ilinx == 1) then
     231            0 :          ii=1+nxm*(zxget-x(1))/(x(nx)-x(1))
     232            0 :          i=min(nxm, ii)
     233            0 :          if(zxget < x(i)) then
     234            0 :             i=i-1
     235            0 :          else if(zxget > x(i+1)) then
     236            0 :             i=i+1
     237              :          end if
     238              :       else
     239            0 :          if((1 <= i).and.(i < nxm)) then
     240            0 :             if((x(i) <= zxget).and.(zxget <= x(i+1))) then
     241              :                continue  ! already have the zone
     242              :             else
     243            0 :                call zonfind_db(x,nx,zxget,i)
     244              :             end if
     245              :          else
     246            0 :             call zonfind_db(x,nx,zxget,i)
     247              :          end if
     248              :       end if
     249              : 
     250            0 :       if(iliny == 1) then
     251            0 :          jj=1+nym*(zyget-y(1))/(y(ny)-y(1))
     252            0 :          j=min(nym, jj)
     253            0 :          if(zyget < y(j)) then
     254            0 :             j=j-1
     255            0 :          else if(zyget > y(j+1)) then
     256            0 :             j=j+1
     257              :          end if
     258              :       else
     259            0 :          if((1 <= j).and.(j < nym)) then
     260            0 :             if((y(j) <= zyget).and.(zyget <= y(j+1))) then
     261              :                continue  ! already have the zone
     262              :             else
     263            0 :                call zonfind_db(y,ny,zyget,j)
     264              :             end if
     265              :          else
     266            0 :             call zonfind_db(y,ny,zyget,j)
     267              :          end if
     268              :       end if
     269              : 
     270            0 :       dx=zxget-x(i)
     271            0 :       dy=zyget-y(j)
     272              : 
     273            0 :       return
     274              :       end subroutine bcspevxy_db
     275              : 
     276              : !------------------------------------------------------------------------
     277              : !  bcspevfn -- OK now evaluate the bicubic spline
     278              : 
     279            0 :       subroutine bcspevfn_db(ict,ivec,ivd,fval,iv,jv,dxv,dyv,f,inf3,ny)
     280              : 
     281              : !  input:
     282              :       integer ny
     283              :       integer ict(6)                    ! selector:
     284              : !        ict(1)=1 for f      (don't evaluate f if ict(1)=0)
     285              : !        ict(2)=1 for df/dx   ""
     286              : !        ict(3)=1 for df/dy   ""
     287              : !        ict(4)=1 for d2f/dx2
     288              : !        ict(5)=1 for d2f/dy2
     289              : !        ict(6)=1 for d2f/dxdy
     290              : 
     291              : !    note:  if ict(1)=-1, evaluate f,d2f/dx2,d2f/dy2,d4f/dx2dy2
     292              : 
     293              : !                   the number of non zero values ict(1:6)
     294              : !                   determines the number of outputs...
     295              : 
     296              : !  new dmc December 2005 -- access to higher derivatives (even if not
     297              : !  continuous-- but can only go up to 3rd derivatives on any one coordinate.
     298              : !     if ict(1)=3 -- want 3rd derivatives
     299              : !          ict(2)=1 for d3f/dx3
     300              : !          ict(3)=1 for d3f/dx2dy
     301              : !          ict(4)=1 for d3f/dxdy2
     302              : !          ict(5)=1 for d3f/dy3
     303              : !               number of non-zero values ict(2:5) gives no. of outputs
     304              : !     if ict(1)=4 -- want 4th derivatives
     305              : !          ict(2)=1 for d4f/dx3dy
     306              : !          ict(3)=1 for d4f/dx2dy2
     307              : !          ict(4)=1 for d4f/dxdy3
     308              : !               number of non-zero values ict(2:4) gives no. of outputs
     309              : !     if ict(1)=5 -- want 5th derivatives
     310              : !          ict(2)=1 for d5f/dx3dy2
     311              : !          ict(3)=1 for d5f/dx2dy3
     312              : !               number of non-zero values ict(2:3) gives no. of outputs
     313              : !     if ict(1)=6 -- want 6th derivatives
     314              : !          d6f/dx3dy3 -- one value is returned.
     315              : 
     316              :       integer ivec,ivd                  ! vector dimensioning
     317              : 
     318              : !    ivec-- number of vector pts (spline values to look up)
     319              : !    ivd -- 1st dimension of fval,  >= ivec
     320              : 
     321              : ! output:
     322              :       real(dp) fval(ivd,6)                 ! output array
     323              : 
     324              : !    v = index to element in vector;
     325              : !  fval(v,1) = first item requested by ict(...),
     326              : !  fval(v,2) = 2nd item requested,  ...etc...
     327              : 
     328              : !  input:
     329              :       integer iv(ivec),jv(ivec)         ! grid cell indices -- vectors
     330              :       real(dp) dxv(ivec),dyv(ivec)          ! displacements w/in cell -- vectors
     331              : 
     332              :       integer inf3                      ! 3rd dimension of f -- >= nx
     333              :       real(dp) f(4,4,inf3,ny)               ! bicubic fcn spline coeffs array
     334              : 
     335              : !  usage example:
     336              : 
     337              : !  1.  for each element (xx(v),yy(v)) in a vector of (x,y) pairs,
     338              : !    find the x and y zone indices and displacements with respect
     339              : !    to the "lower left corner" of the zone; store these in vectors
     340              : !    iv,jv and dxv,dyv.
     341              : 
     342              : !  2.  set ict(1)=0, ict(2)=1, ict(3)=1, the rest zero -- get only
     343              : !      the 1st derivatives.
     344              : 
     345              : !  3.  ivec is the length of the vector; ivd is the 1st dimension
     346              : !      of the array fval to receive the output
     347              : 
     348              : !      real(dp) fval(ivd,6)
     349              : !      real(dp) xv(ivd),yv(ivd)
     350              : !      integer iv(ivd),jv(ivd)
     351              : !      real(dp) dxv(ivd),dyv(ivd)
     352              : !      integer ict(6)
     353              : 
     354              : !      real(dp) fspline(4,4,nx,ny)  ! spline coeffs
     355              : !      data ict/0,1,1,0,0,0/    ! this call:  want 1st derivatives
     356              : !                               ! only ... these will be output to
     357              : !                               ! fval(*,1) fval(*,2)
     358              : !      ...
     359              : !      do iv=1,ivec
     360              : !        ...                    ! find indices and displacements
     361              : !      end do
     362              : !      call bcspevfn(ict,ivec,ivd,fval,iv,jv,dxv,dyv,fspline,nx,ny)
     363              : 
     364              : !-------------------------------------------------------------------
     365              : !  local:
     366              : 
     367              :       integer v                         ! vector element index
     368              : 
     369              : !  OK can now do evaluations
     370              : 
     371            0 :       iaval=0  ! fval addressing
     372              : 
     373            0 :       if(ict(1) <= 2) then
     374            0 :          if((ict(1) > 0).or.(ict(1) == -1)) then
     375              : !  evaluate f
     376            0 :             iaval=iaval+1
     377            0 :             do v=1,ivec
     378            0 :                i=iv(v)
     379            0 :                j=jv(v)
     380            0 :                dx=dxv(v)
     381            0 :                dy=dyv(v)
     382              :                fval(v,iaval)=
     383              :      &       f(1,1,i,j)+dy*(f(1,2,i,j)+dy*(f(1,3,i,j)+dy*f(1,4,i,j)))
     384              :      &  +dx*(f(2,1,i,j)+dy*(f(2,2,i,j)+dy*(f(2,3,i,j)+dy*f(2,4,i,j)))
     385              :      &  +dx*(f(3,1,i,j)+dy*(f(3,2,i,j)+dy*(f(3,3,i,j)+dy*f(3,4,i,j)))
     386            0 :      &  +dx*(f(4,1,i,j)+dy*(f(4,2,i,j)+dy*(f(4,3,i,j)+dy*f(4,4,i,j))))))
     387              :             end do
     388              :          end if
     389              : 
     390            0 :          if((ict(2) > 0).and.(ict(1) /= -1)) then
     391              : !  evaluate df/dx
     392            0 :             iaval=iaval+1
     393            0 :             do v=1,ivec
     394            0 :                i=iv(v)
     395            0 :                j=jv(v)
     396            0 :                dx=dxv(v)
     397            0 :                dy=dyv(v)
     398              :                fval(v,iaval)=
     399              :      &         f(2,1,i,j)+dy*(f(2,2,i,j)+dy*(f(2,3,i,j)+dy*f(2,4,i,j)))
     400              :      &       +2.d0*dx*(
     401              :      &         f(3,1,i,j)+dy*(f(3,2,i,j)+dy*(f(3,3,i,j)+dy*f(3,4,i,j)))
     402              :      &       +1.5d0*dx*(
     403              :      &         f(4,1,i,j)+dy*(f(4,2,i,j)+dy*(f(4,3,i,j)+dy*f(4,4,i,j)))
     404            0 :      &              ))
     405              :             end do
     406              :          end if
     407              : 
     408            0 :          if((ict(3) > 0).and.(ict(1) /= -1)) then
     409              : !  evaluate df/dy
     410            0 :             iaval=iaval+1
     411            0 :             do v=1,ivec
     412            0 :                i=iv(v)
     413            0 :                j=jv(v)
     414            0 :                dx=dxv(v)
     415            0 :                dy=dyv(v)
     416              :                fval(v,iaval)=
     417              :      &         f(1,2,i,j)+dy*(2.d0*f(1,3,i,j)+dy*3.d0*f(1,4,i,j))
     418              :      &      +dx*(f(2,2,i,j)+dy*(2.d0*f(2,3,i,j)+dy*3.d0*f(2,4,i,j))
     419              :      &      +dx*(f(3,2,i,j)+dy*(2.d0*f(3,3,i,j)+dy*3.d0*f(3,4,i,j))
     420              :      &      +dx*(f(4,2,i,j)+dy*(2.d0*f(4,3,i,j)+dy*3.d0*f(4,4,i,j))
     421            0 :      &              )))
     422              :             end do
     423              :          end if
     424              : 
     425            0 :          if((ict(4) > 0).or.(ict(1) == -1)) then
     426              : !  evaluate d2f/dx2
     427            0 :             iaval=iaval+1
     428            0 :             do v=1,ivec
     429            0 :                i=iv(v)
     430            0 :                j=jv(v)
     431            0 :                dx=dxv(v)
     432            0 :                dy=dyv(v)
     433              :                fval(v,iaval)=
     434              :      &              2.d0*(
     435              :      &              f(3,1,i,j)+dy*(f(3,2,i,j)+dy*(f(3,3,i,j)+dy*f(3,4,i,j))))
     436              :      &              +6.d0*dx*(
     437            0 :      &              f(4,1,i,j)+dy*(f(4,2,i,j)+dy*(f(4,3,i,j)+dy*f(4,4,i,j))))
     438              :             end do
     439              :          end if
     440              : 
     441            0 :          if((ict(5) > 0).or.(ict(1) == -1)) then
     442              : !  evaluate d2f/dy2
     443            0 :             iaval=iaval+1
     444            0 :             do v=1,ivec
     445            0 :                i=iv(v)
     446            0 :                j=jv(v)
     447            0 :                dx=dxv(v)
     448            0 :                dy=dyv(v)
     449              :                fval(v,iaval)=
     450              :      &              2.d0*f(1,3,i,j)+6.d0*dy*f(1,4,i,j)
     451              :      &              +dx*(2.d0*f(2,3,i,j)+6.d0*dy*f(2,4,i,j)
     452              :      &              +dx*(2.d0*f(3,3,i,j)+6.d0*dy*f(3,4,i,j)
     453            0 :      &              +dx*(2.d0*f(4,3,i,j)+6.d0*dy*f(4,4,i,j))))
     454              :             end do
     455              :          end if
     456              : 
     457            0 :          if((ict(6) > 0).and.(ict(1) /= -1)) then
     458              : !  evaluate d2f/dxdy
     459            0 :             iaval=iaval+1
     460            0 :             do v=1,ivec
     461            0 :                i=iv(v)
     462            0 :                j=jv(v)
     463            0 :                dx=dxv(v)
     464            0 :                dy=dyv(v)
     465              :                fval(v,iaval)=
     466              :      &            f(2,2,i,j)+dy*(2.d0*f(2,3,i,j)+dy*3.d0*f(2,4,i,j))
     467              :      & +2.d0*dx*(f(3,2,i,j)+dy*(2.d0*f(3,3,i,j)+dy*3.d0*f(3,4,i,j))
     468              :      &+1.5d0*dx*(f(4,2,i,j)+dy*(2.d0*f(4,3,i,j)+dy*3.d0*f(4,4,i,j))
     469            0 :      &              ))
     470              :             end do
     471              :          end if
     472              : 
     473            0 :          if(ict(1) == -1) then
     474            0 :             iaval=iaval+1
     475            0 :             do v=1,ivec
     476            0 :                i=iv(v)
     477            0 :                j=jv(v)
     478            0 :                dx=dxv(v)
     479            0 :                dy=dyv(v)
     480              :                fval(v,iaval)=
     481              :      &              4.d0*f(3,3,i,j)+12.d0*dy*f(3,4,i,j)
     482            0 :      &              +dx*(12.d0*f(4,3,i,j)+36.d0*dy*f(4,4,i,j))
     483              :             end do
     484              :          end if
     485              : 
     486              : !-----------------------------------
     487              : !  access to 3rd derivatives
     488              : 
     489            0 :       else if(ict(1) == 3) then
     490            0 :          if(ict(2) == 1) then
     491              : !  evaluate d3f/dx3 (not continuous)
     492            0 :             iaval=iaval+1
     493            0 :             do v=1,ivec
     494            0 :                i=iv(v)
     495            0 :                j=jv(v)
     496            0 :                dy=dyv(v)
     497              :                fval(v,iaval)=
     498              :      &              +6.d0*(
     499            0 :      &         f(4,1,i,j)+dy*(f(4,2,i,j)+dy*(f(4,3,i,j)+dy*f(4,4,i,j))))
     500              :             end do
     501              :          end if
     502              : 
     503            0 :          if(ict(3) == 1) then
     504              : !  evaluate d3f/dx2dy
     505            0 :             iaval=iaval+1
     506            0 :             do v=1,ivec
     507            0 :                i=iv(v)
     508            0 :                j=jv(v)
     509            0 :                dx=dxv(v)
     510            0 :                dy=dyv(v)
     511              :                fval(v,iaval)=
     512              :      &              2.d0*(
     513              :      &           f(3,2,i,j)+dy*(2.d0*f(3,3,i,j)+dy*3.d0*f(3,4,i,j)))
     514              :      &              +6.d0*dx*(
     515            0 :      &           f(4,2,i,j)+dy*(2.d0*f(4,3,i,j)+dy*3.d0*f(4,4,i,j)))
     516              :             end do
     517              :          end if
     518              : 
     519            0 :          if(ict(4) == 1) then
     520              : !  evaluate d3f/dxdy2
     521            0 :             iaval=iaval+1
     522            0 :             do v=1,ivec
     523            0 :                i=iv(v)
     524            0 :                j=jv(v)
     525            0 :                dx=dxv(v)
     526            0 :                dy=dyv(v)
     527              :                fval(v,iaval)=
     528              :      &              (2.d0*f(2,3,i,j)+6.d0*dy*f(2,4,i,j)
     529              :      &              +2.d0*dx*(2.d0*f(3,3,i,j)+6.d0*dy*f(3,4,i,j)
     530              :      &              +1.5d0*dx*(2.d0*f(4,3,i,j)+6.d0*dy*f(4,4,i,j))
     531            0 :      &              ))
     532              :             end do
     533              :          end if
     534              : 
     535            0 :          if(ict(5) == 1) then
     536              : !  evaluate d3f/dy3 (not continuous)
     537            0 :             iaval=iaval+1
     538            0 :             do v=1,ivec
     539            0 :                i=iv(v)
     540            0 :                j=jv(v)
     541            0 :                dx=dxv(v)
     542              :                fval(v,iaval)=6.d0*(f(1,4,i,j)+
     543            0 :      &              dx*(f(2,4,i,j)+dx*(f(3,4,i,j)+dx*f(4,4,i,j))))
     544              :             end do
     545              :          end if
     546              : 
     547              : !-----------------------------------
     548              : !  access to 4th derivatives
     549              : 
     550            0 :       else if(ict(1) == 4) then
     551            0 :          if(ict(2) == 1) then
     552              : !  evaluate d4f/dx3dy (not continuous)
     553            0 :             iaval=iaval+1
     554            0 :             do v=1,ivec
     555            0 :                i=iv(v)
     556            0 :                j=jv(v)
     557            0 :                dy=dyv(v)
     558              :                fval(v,iaval)=
     559              :      &              +6.d0*(
     560            0 :      &         f(4,2,i,j)+dy*2.d0*(f(4,3,i,j)+dy*1.5d0*f(4,4,i,j)))
     561              :             end do
     562              :          end if
     563              : 
     564            0 :          if(ict(3) == 1) then
     565              : !  evaluate d4f/dx2dy2
     566            0 :             iaval=iaval+1
     567            0 :             do v=1,ivec
     568            0 :                i=iv(v)
     569            0 :                j=jv(v)
     570            0 :                dx=dxv(v)
     571            0 :                dy=dyv(v)
     572              :                fval(v,iaval)=
     573              :      &              4.d0*f(3,3,i,j)+12.d0*dy*f(3,4,i,j)
     574            0 :      &              +dx*(12.d0*f(4,3,i,j)+36.d0*dy*f(4,4,i,j))
     575              :             end do
     576              :          end if
     577              : 
     578            0 :          if(ict(4) == 1) then
     579              : !  evaluate d4f/dxdy3 (not continuous)
     580            0 :             iaval=iaval+1
     581            0 :             do v=1,ivec
     582            0 :                i=iv(v)
     583            0 :                j=jv(v)
     584            0 :                dx=dxv(v)
     585              :                fval(v,iaval)=
     586              :      &              6.d0*(f(2,4,i,j)
     587            0 :      &              +2.d0*dx*(f(3,4,i,j)+1.5d0*dx*f(4,4,i,j)))
     588              :             end do
     589              :          end if
     590              : 
     591              : !-----------------------------------
     592              : !  access to 5th derivatives
     593              : 
     594            0 :       else if(ict(1) == 5) then
     595            0 :          if(ict(2) == 1) then
     596              : !  evaluate d5f/dx3dy2 (not continuous)
     597            0 :             iaval=iaval+1
     598            0 :             do v=1,ivec
     599            0 :                i=iv(v)
     600            0 :                j=jv(v)
     601            0 :                dy=dyv(v)
     602              :                fval(v,iaval)=
     603            0 :      &              +12.d0*(f(4,3,i,j)+dy*3.d0*f(4,4,i,j))
     604              :             end do
     605              :          end if
     606              : 
     607            0 :          if(ict(3) == 1) then
     608              : !  evaluate d5f/dx3dy2 (not continuous)
     609            0 :             iaval=iaval+1
     610            0 :             do v=1,ivec
     611            0 :                i=iv(v)
     612            0 :                j=jv(v)
     613            0 :                dx=dxv(v)
     614              :                fval(v,iaval)=
     615            0 :      &              12.d0*(f(3,4,i,j)+dx*3.d0*f(4,4,i,j))
     616              :             end do
     617              :          end if
     618              : 
     619              : !-----------------------------------
     620              : !  access to 6th derivatives
     621              : 
     622            0 :       else if(ict(1) == 6) then
     623              : !  evaluate d6f/dx3dy3 (not continuous)
     624            0 :          iaval=iaval+1
     625            0 :          do v=1,ivec
     626            0 :             i=iv(v)
     627            0 :             j=jv(v)
     628              :             fval(v,iaval)=
     629            0 :      &              36.d0*f(4,4,i,j)
     630              :          end do
     631              :       end if
     632              : 
     633            0 :       return
     634              :       end subroutine bcspevfn_db
     635              : 
     636              : !----------------------
     637              : 
     638              : !  bcspline -- dmc 30 May 1996
     639              : 
     640              : !  set up coefficients for bicubic spline with following BC's:
     641              : !  FULL BC CONTROL at all bdys
     642              : 
     643              : !  inhomogeneous explicit BCs -- this means setting of 1st or 2nd
     644              : !  derivative at boundary to a non-zero value.
     645              : 
     646              : !  periodic, not-a-knot, zero derivative, and divided-difference based
     647              : !  BCs are "homogeneous"-- i.e. if splines s & t satisfy the BC then
     648              : !  the spline (c*s + t) formed as a linear combination of these two
     649              : !  splines, also satisfies the BC.
     650              : 
     651              : !  algorithm note -- handling of inhomogeneous explicit BC's while
     652              : !  maintaining full C2 differentiability is delicate.  Basic method:  use
     653              : !  a fully C2 method based on the "not-a-knot" BC, and then, correct to
     654              : !  meet each user BC by calculating a C2 spline that is zero at all grid
     655              : !  points but satisfies a BC which is the difference btw the user spec
     656              : !  and the not-a-knot result; add the coeffs of this into the original.
     657              : 
     658              : !  for this more workspace is needed: nwk >= 4*inx*inth +5*max(inx,inth)
     659              : 
     660            0 :       subroutine bcspline_db(x,inx,th,inth,fspl,inf3,
     661            0 :      &                    ibcxmin,bcxmin,ibcxmax,bcxmax,
     662            0 :      &                    ibcthmin,bcthmin,ibcthmax,bcthmax,
     663            0 :      &                    wk,nwk,ilinx,ilinth,ier)
     664              : 
     665              :       implicit none
     666              :       integer inx, inth, inf3, nwk, ibcxmin, ibcxmax, ibcthmin, ibcthmax, ilinx,ilinth,ier
     667              :       real(dp) x(inx),th(inth),fspl(4,4,inf3,inth),wk(nwk)
     668              :       real(dp) bcxmin(inth),bcxmax(inth)
     669              :       real(dp) bcthmin(inx),bcthmax(inx)
     670              : 
     671              : !  input:
     672              : !    x(1...inx) -- abscissae, first dimension of data
     673              : !   th(1...inth) -- abscissae, second dimension of data  f(x,th)
     674              : !   fspl(1,1,1..inx,1..inth) -- function values
     675              : !   inf3 -- fspl dimensioning, inf3 >= inx required.
     676              : 
     677              : !  boundary conditions input:
     678              : !   ibcxmin -- indicator for boundary condition at x(1):
     679              : !    bcxmin(...) -- boundary condition data
     680              : !     =-1 -- periodic boundary condition
     681              : !     =0 -- use "not a knot", bcxmin(...) ignored
     682              : !     =1 -- match slope, specified at x(1),th(ith) by bcxmin(ith)
     683              : !     =2 -- match 2nd derivative, specified at x(1),th(ith) by bcxmin(ith)
     684              : !     =3 -- boundary condition is slope=0 (df/dx=0) at x(1), all th(j)
     685              : !     =4 -- boundary condition is d2f/dx2=0 at x(1), all th(j)
     686              : !     =5 -- match 1st derivative df/dx to 1st divided difference
     687              : !     =6 -- match 2nd derivative d2f/dx2 to 2nd divided difference
     688              : !     =7 -- match 3rd derivative d3f/dx3 3rd divided difference
     689              : !           (for more detailed definition of BCs 5-7, see the
     690              : !           comments of subroutine mkspline)
     691              : !   NOTE bcxmin(...) referenced ONLY if ibcxmin=1 or ibcxmin=2
     692              : 
     693              : !   ibcxmax -- indicator for boundary condition at x(nx):
     694              : !    bcxmax(...) -- boundary condition data
     695              : !     (interpretation as with ibcxmin, bcxmin)
     696              : !   NOTE:  if ibcxmin=-1, ibcxmax is ignored! ...and the BC is periodic.
     697              : 
     698              : !   ibcthmin -- indicator for boundary condition at th(1):
     699              : !    bcthmin(...) -- boundary condition data
     700              : !     (interpretation as with ibcxmin, bcxmin)
     701              : !   ibcthmax -- indicator for boundary condition at th(inth):
     702              : !    bcthmax(...) -- boundary condition data
     703              : !     (interpretation as with ibcxmin, bcxmin)
     704              : !   NOTE:  if ibcthmin=-1, ibcthmax is ignored! ...and the BC is periodic.
     705              : 
     706              : !   NOTE the bcxmin,bcxmax,bcthmin,bcthmax arrays are only used if the
     707              : !     corresponding boundary condition flags are set to 1 or 2.
     708              : !     Carefully note the dimensioning of these arrays!
     709              : 
     710              : !  output:
     711              : !   fspl(*,*,1..inx,1..inth) -- bicubic spline coeffs (4x4)
     712              : !   ...fspl(1,1,*,*) is not replaced.
     713              : 
     714              : !   ilinx -- =1 on output if x(inx) pts are nearly evenly spaced (tol=1e-3)
     715              : !   ilinth-- =1 on output if th(inth) evenly spaced (tol=1e-3)
     716              : 
     717              : !   ier -- completion code, 0 for normal
     718              : 
     719              : !  workspace:
     720              : !   wk -- must be at least 5*max(inx,inth) large
     721              : !                          5*max(inx,inth) + 4*inx*inth large
     722              : !                          if explicit non-zero d/dth or d2/dth2 BC's
     723              : !                          are supplied.
     724              : !  nwk -- size of workspace of workspace provided
     725              : 
     726              : !---------------------------------
     727              : !  in what follows, "f" is an abbreviation for "fspl"...
     728              : 
     729              : !  compute bicubic spline of 2d function, given values at the grid
     730              : !  grid crossing points, f(1,1,i,j)=f(x(i),th(j)).
     731              : 
     732              : !  on evaluation:  for point x btw x(i) and x(i+1), dx=x-x(i)
     733              : !                       and th btw th(j) and th(j+1), dt=th-th(j),
     734              : 
     735              : !      spline =
     736              : !        f(1,1,i,j) + dx*f(2,1,i,j) + dx**2*f(3,1,i,j) + dx**3*f(4,1,i,j)
     737              : !   +dt*(f(1,2,i,j) + dx*f(2,2,i,j) + dx**2*f(3,2,i,j) + dx**3*f(4,2,i,j))
     738              : !   +d2*(f(1,3,i,j) + dx*f(2,3,i,j) + dx**2*f(3,3,i,j) + dx**3*f(4,3,i,j))
     739              : !   +d3*(f(1,4,i,j) + dx*f(2,4,i,j) + dx**2*f(3,4,i,j) + dx**3*f(4,4,i,j))
     740              : 
     741              : !      where d2=dt**2 and d3=dt**3.
     742              : 
     743              :       integer iselect1(10)
     744              :       integer iselect2(10)
     745              : 
     746              : 
     747              :       integer iflg2, ix, itest, ierx, inxo, ith, jth, ii, iadr, ia5w, iaspl, ierth, intho, ic
     748              :       integer ibcthmina, ibcthmaxa, iasc, iinc, iawk, jx
     749            0 :       real(dp) xo2, xo6, zcur, zdiff1, zhxn, zhth, zdiff2
     750            0 :       real(dp) fval(6)
     751              : 
     752              : !---------------------------------
     753              : 
     754              : !  see if 2nd pass is needed due to "non-linear" d/dth bdy cond.
     755              : 
     756            0 :       iflg2=0
     757            0 :       if(ibcthmin /= -1) then
     758            0 :          if((ibcthmin == 1).or.(ibcthmin == 2)) then
     759            0 :             do ix=1,inx
     760            0 :                if (bcthmin(ix) /= 0.d0) iflg2=1
     761              :             end do
     762              :          end if
     763            0 :          if((ibcthmax == 1).or.(ibcthmax == 2)) then
     764            0 :             do ix=1,inx
     765            0 :                if (bcthmax(ix) /= 0.d0) iflg2=1
     766              :             end do
     767              :          end if
     768              :       end if
     769              : 
     770            0 :       ier=0
     771            0 :       itest=5*max(inx,inth)
     772            0 :       if(iflg2 == 1) then
     773            0 :          itest=itest +4*inx*inth
     774              :       end if
     775              : 
     776            0 :       if(nwk < itest) then
     777            0 :          write(6,9901) nwk,itest
     778              :  9901    format(' ?bcspline:  workspace too small:'/
     779              :      &          '  user supplied:  nwk=',i6,'; need at least:  ',i6/
     780              :      &          '  nwk=4*nx*ny +5*max(nx,ny) will work for any user'/
     781              :      &          '  choice of bdy conditions.')
     782            0 :          ier=1
     783              :       end if
     784            0 :       if(inx < 4) then
     785            0 :          write(6,'('' ?bcspline:  at least 4 x points required.'')')
     786            0 :          ier=1
     787              :       end if
     788            0 :       if(inth < 4) then
     789            0 :          write(6,'('' ?bcspline:  need at least 4 theta points.'')')
     790            0 :          ier=1
     791              :       end if
     792              : 
     793            0 :       call ibc_ck_db(ibcxmin,'bcspline','xmin',-1,7,ier)
     794            0 :       if(ibcxmin >= 0) call ibc_ck_db(ibcxmax,'bcspline','xmax',0,7,ier)
     795            0 :       call ibc_ck_db(ibcthmin,'bcspline','thmin',-1,7,ier)
     796            0 :       if(ibcthmin >= 0) call ibc_ck_db(ibcthmax,'bcspline','thmax',0,7,ier)
     797              : 
     798              : !  check ilinx & x vector
     799              : 
     800            0 :       call splinck_db(x,inx,ilinx,1.0d-3,ierx)
     801            0 :       if(ierx /= 0) ier=2
     802              : 
     803            0 :       if(ier == 2) then
     804            0 :          write(6,'('' ?bcspline:  x axis not strict ascending'')')
     805              :       end if
     806              : 
     807              : !  check ilinth & th vector
     808              : 
     809            0 :       call splinck_db(th,inth,ilinth,1.0d-3,ierth)
     810            0 :       if(ierth /= 0) ier=3
     811              : 
     812              : !      if(ier == 3) then
     813              : !         write(6,'('' ?bcspline:  th axis not strict ascending'')')
     814              : !      end if
     815              : 
     816            0 :       if(ier /= 0) return
     817              : 
     818              : !------------------------------------
     819              : 
     820            0 :       xo2=0.5d0
     821            0 :       xo6=1.d0/6.d0
     822              : 
     823              : !  spline in x direction
     824              : 
     825            0 :       inxo=4*(inx-1)
     826            0 :       do ith=1,inth
     827              : 
     828              : !  copy the function in
     829              : 
     830            0 :          do ix=1,inx
     831            0 :             wk(4*(ix-1)+1)=fspl(1,1,ix,ith)
     832              :          end do
     833              : 
     834            0 :          if(ibcxmin == 1) then
     835            0 :             wk(2)=bcxmin(ith)
     836            0 :          else if(ibcxmin == 2) then
     837            0 :             wk(3)=bcxmin(ith)
     838              :          end if
     839              : 
     840            0 :          if(ibcxmax == 1) then
     841            0 :             wk(inxo+2)=bcxmax(ith)
     842            0 :          else if(ibcxmax == 2) then
     843            0 :             wk(inxo+3)=bcxmax(ith)
     844              :          end if
     845              : 
     846              : !  use Wayne's routine
     847              : 
     848            0 :          call v_spline_db(ibcxmin,ibcxmax,inx,x,wk,wk(4*inx+1))
     849              : 
     850              : !  copy the coefficients out
     851              : 
     852            0 :          do ix=1,inx
     853            0 :             fspl(2,1,ix,ith)=wk(4*(ix-1)+2)
     854            0 :             fspl(3,1,ix,ith)=wk(4*(ix-1)+3)*xo2
     855            0 :             fspl(4,1,ix,ith)=wk(4*(ix-1)+4)*xo6
     856              :          end do
     857              : 
     858              :       end do
     859              : 
     860              : !-----------------------------------
     861              : 
     862              : !  spline in theta direction
     863              : 
     864            0 :       intho=4*(inth-1)
     865            0 :       do ix=1,inx
     866              : 
     867              : !  spline each x coeff
     868              : 
     869            0 :          do ic=1,4
     870              : 
     871              : !  copy ordinates in
     872              : 
     873            0 :             do ith=1,inth
     874            0 :                wk(4*(ith-1)+1)=fspl(ic,1,ix,ith)
     875              :             end do
     876              : 
     877              : !  first pass:  use a linear BC -- if flag indicates BC correction
     878              : !  will be needed, it will be done later
     879              : 
     880            0 :             wk(2)=0.d0
     881            0 :             wk(3)=0.d0
     882            0 :             wk(intho+2)=0.d0
     883            0 :             wk(intho+3)=0.d0
     884              : 
     885            0 :             ibcthmina=ibcthmin
     886            0 :             ibcthmaxa=ibcthmax
     887            0 :             if(iflg2 == 1) then
     888            0 :                if((ibcthmin == 1).or.(ibcthmin == 2)) ibcthmina=0
     889            0 :                if((ibcthmax == 1).or.(ibcthmax == 2)) ibcthmaxa=0
     890              :             end if
     891              : 
     892            0 :             call v_spline_db(ibcthmina,ibcthmaxa,inth,th,wk,wk(4*inth+1))
     893              : 
     894              : !  copy coeffs out
     895              : 
     896            0 :             do ith=1,inth
     897            0 :                fspl(ic,2,ix,ith)=wk(4*(ith-1)+2)
     898            0 :                fspl(ic,3,ix,ith)=wk(4*(ith-1)+3)*xo2
     899            0 :                fspl(ic,4,ix,ith)=wk(4*(ith-1)+4)*xo6
     900              :             end do
     901              : 
     902              :          end do
     903              : 
     904              :       end do
     905              : 
     906              : !  now make correction for user BC's if needed
     907              : 
     908            0 :       if(iflg2 == 1) then
     909              : 
     910            0 :          iasc=1                         ! wk addr for correction splines
     911            0 :          iinc=4*inth                    ! spacing btw correction splines
     912            0 :          iawk=iasc+4*inth*inx
     913              : 
     914              : !  last grid zone widths
     915              : 
     916            0 :          zhxn=x(inx)-x(inx-1)
     917            0 :          jx=inx-1
     918            0 :          zhth=th(inth)-th(inth-1)
     919            0 :          jth=inth-1
     920              : 
     921            0 :          do ii=1,10
     922            0 :             iselect1(ii)=0
     923            0 :             iselect2(ii)=0
     924              :          end do
     925              :          if(ibcthmin == 1) iselect1(3)=1
     926              :          if(ibcthmin == 2) iselect1(5)=1
     927            0 :          if(ibcthmax == 1) iselect2(3)=1
     928            0 :          if(ibcthmax == 2) iselect2(5)=1
     929              : 
     930              : !  loop over BC's
     931              : 
     932            0 :          do ix=1,inx
     933              : 
     934              : !  (a) d/dth @ th(1) difference btw current BC and user request
     935              : 
     936            0 :             if(ibcthmin == 1) then
     937            0 :                if(ix < inx) then
     938            0 :                   zcur=fspl(1,2,ix,1)   ! 1st deriv.
     939              :                else
     940              :                   zcur=fspl(1,2,jx,1)+zhxn*(fspl(2,2,jx,1)+zhxn*
     941            0 :      &               (fspl(3,2,jx,1)+zhxn*fspl(4,2,jx,1)))
     942              :                end if
     943            0 :                zdiff1=bcthmin(ix)-zcur
     944            0 :             else if(ibcthmin == 2) then
     945            0 :                if(ix < inx) then
     946            0 :                   zcur=2.d0*fspl(1,3,ix,1) ! 2nd deriv.
     947              :                else
     948              :                   zcur=2.d0*(fspl(1,3,jx,1)+zhxn*(fspl(2,3,jx,1)+zhxn*
     949            0 :      &               (fspl(3,3,jx,1)+zhxn*fspl(4,3,jx,1))))
     950              :                end if
     951            0 :                zdiff1=bcthmin(ix)-zcur
     952              :             else
     953              :                zdiff1=0.d0
     954              :             end if
     955              : 
     956              : !  (b) d/dth @ th(inth) difference btw current BC and user request
     957              : 
     958            0 :             if(ibcthmax == 1) then
     959            0 :                if(ix < inx) then
     960              : !  1st deriv.
     961              :                   zcur=fspl(1,2,ix,jth)+zhth*(2.d0*fspl(1,3,ix,jth)+
     962            0 :      &               zhth*3.d0*fspl(1,4,ix,jth))
     963              :                else
     964              :                   call bcspeval_db(x(inx),th(inth),iselect2,fval,
     965            0 :      &               x,inx,th,inth,ilinx,ilinth,fspl,inf3,ier)
     966            0 :                   zcur=fval(1)
     967            0 :                   if(ier /= 0) return
     968              :                end if
     969            0 :                zdiff2=bcthmax(ix)-zcur
     970            0 :             else if(ibcthmax == 2) then
     971            0 :                if(ix < inx) then
     972              : !  2nd deriv.
     973              :                   zcur=2.d0*fspl(1,3,ix,jth)+
     974            0 :      &               6.d0*zhth*fspl(1,4,ix,jth)
     975              :                else
     976              :                   call bcspeval_db(x(inx),th(inth),iselect2,fval,
     977            0 :      &               x,inx,th,inth,ilinx,ilinth,fspl,inf3,ier)
     978            0 :                   zcur=fval(1)
     979            0 :                   if(ier /= 0) return
     980              :                end if
     981            0 :                zdiff2=bcthmax(ix)-zcur
     982              :             else
     983              :                zdiff2=0.d0
     984              :             end if
     985              : 
     986              : !  ok compute the theta spline with BC's to span the difference(s)
     987              : !  these theta "correction splines" are zero at all the grid points
     988              : !  but have at least one non-zero 1st or 2nd derivative BC
     989              : 
     990            0 :             iadr=iasc+(ix-1)*iinc
     991            0 :             do ith=1,inth
     992            0 :                wk(iadr+4*(ith-1))=0.d0
     993              :             end do
     994              : 
     995            0 :             wk(iadr+1)=0.d0
     996            0 :             wk(iadr+2)=0.d0
     997            0 :             wk(iadr+intho+1)=0.d0
     998            0 :             wk(iadr+intho+2)=0.d0
     999              : 
    1000            0 :             if(ibcthmin == 1) then
    1001            0 :                wk(iadr+1)=zdiff1
    1002            0 :             else if(ibcthmin == 2) then
    1003            0 :                wk(iadr+2)=zdiff1
    1004              :             end if
    1005              : 
    1006            0 :             if(ibcthmax == 1) then
    1007            0 :                wk(iadr+intho+1)=zdiff2
    1008            0 :             else if(ibcthmax == 2) then
    1009            0 :                wk(iadr+intho+2)=zdiff2
    1010              :             end if
    1011              : 
    1012            0 :             call v_spline_db(ibcthmin,ibcthmax,inth,th,wk(iadr),wk(iawk))
    1013              :          end do
    1014              : 
    1015              : !  add in results to main array -- th spline coef corrections
    1016              : 
    1017            0 :          do ix=1,inx
    1018            0 :             iadr=iasc+(ix-1)*iinc
    1019            0 :             do ith=1,inth-1
    1020            0 :                wk(iadr+4*(ith-1)+2)=wk(iadr+4*(ith-1)+2)*xo2
    1021            0 :                wk(iadr+4*(ith-1)+3)=wk(iadr+4*(ith-1)+3)*xo6
    1022            0 :                if(ix < inx) then
    1023            0 :                   fspl(1,2,ix,ith)=fspl(1,2,ix,ith)+wk(iadr+4*(ith-1)+1)
    1024            0 :                   fspl(1,3,ix,ith)=fspl(1,3,ix,ith)+wk(iadr+4*(ith-1)+2)
    1025            0 :                   fspl(1,4,ix,ith)=fspl(1,4,ix,ith)+wk(iadr+4*(ith-1)+3)
    1026              :                end if
    1027              :             end do
    1028              :          end do
    1029              : 
    1030              : !  compute the x splines of the th spline correction coeffs
    1031              : 
    1032            0 :          ia5w=iawk+4*inx
    1033              : 
    1034            0 :          do ith=1,inth-1
    1035            0 :             do ic=2,4
    1036            0 :                do ix=1,inx
    1037            0 :                   iaspl=iasc+iinc*(ix-1)
    1038            0 :                   wk(iawk+4*(ix-1))=wk(iaspl+4*(ith-1)+(ic-1))
    1039              :                end do
    1040              : 
    1041              : !  use zero BCs for this correction spline
    1042              : 
    1043            0 :                wk(iawk+1)=0.d0
    1044            0 :                wk(iawk+2)=0.d0
    1045            0 :                wk(iawk+inxo+1)=0.d0
    1046            0 :                wk(iawk+inxo+2)=0.d0
    1047              : 
    1048              : !  periodic spline of correction spline higher coeffs (1st coeffs are
    1049              : !  all zero by defn of the correction spline
    1050              : 
    1051            0 :                call v_spline_db(ibcxmin,ibcxmax,inx,x,wk(iawk),wk(ia5w))
    1052              : 
    1053            0 :                do ix=1,inx-1
    1054              :                   fspl(2,ic,ix,ith)=fspl(2,ic,ix,ith)+
    1055            0 :      &               wk(iawk+4*(ix-1)+1)
    1056              :                   fspl(3,ic,ix,ith)=fspl(3,ic,ix,ith)+
    1057            0 :      &               wk(iawk+4*(ix-1)+2)*xo2
    1058              :                   fspl(4,ic,ix,ith)=fspl(4,ic,ix,ith)+
    1059            0 :      &               wk(iawk+4*(ix-1)+3)*xo6
    1060              :                end do
    1061              : 
    1062              :             end do
    1063              :          end do                          ! ith
    1064              : 
    1065              :       end if                             ! BC correction needs test
    1066              : 
    1067              :       return
    1068              :       end subroutine bcspline_db
    1069              : 
    1070              : !  cspline -- dmc 15 Feb 1999
    1071              : 
    1072              : !  a standard interface to the 1d spline setup routine
    1073              : !    modified dmc 3 Mar 2000 -- to use Wayne Houlberg's v_spline code.
    1074              : !    new BC options added.
    1075              : 
    1076      6806634 :       subroutine cspline_db(x,nx,fspl,ibcxmin,bcxmin,ibcxmax,bcxmax,
    1077      6806634 :      &   wk,iwk,ilinx,ier)
    1078              : 
    1079              :       implicit none
    1080              :       integer nx, iwk
    1081              :       real(dp) x(nx)                        ! x axis (in)
    1082              :       real(dp) fspl(4,nx)                   ! spline data (in/out)
    1083              :       integer ibcxmin                   ! x(1) BC flag (in, see comments)
    1084              :       real(dp) bcxmin                       ! x(1) BC data (in, see comments)
    1085              :       integer ibcxmax                   ! x(nx) BC flag (in, see comments)
    1086              :       real(dp) bcxmax                       ! x(nx) BC data (in, see comments)
    1087              :       real(dp) wk(iwk)                      ! workspace of size at least nx
    1088              :       integer ilinx                     ! even spacing flag (out)
    1089              :       integer ier                       ! output, =0 means OK
    1090              : 
    1091              : !  ** note wk(...) array is not used unless ibcxmin=-1 (periodic spline
    1092              : !  evaluation)
    1093              : 
    1094              : !  this routine computes spline coefficients for a 1d spline --
    1095              : !  evaluation of the spline can be done by cspeval.for subroutines
    1096              : !  or directly by inline code.
    1097              : 
    1098              : !  the input x axis x(1...nx) must be strictly ascending, i.e.
    1099              : !  x(i+1) > x(i) is required for i=1 to nx-1.  This is checked and
    1100              : !  ier=1 is set and the routine exits if the test is not satisfied.
    1101              : 
    1102              : !  on output, ilinx=1 is set if, to a reasonably close tolerance,
    1103              : !  all grid spacings x(i+1)-x(i) are equal.  This allows a speedier
    1104              : !  grid lookup algorithm on evaluation of the spline.  If on output
    1105              : !  ilinx=2, this means the spline x axis is not evenly spaced.
    1106              : 
    1107              : !  the input data for the spline are given in f[j] = fspl(1,j).  The
    1108              : !  output data are the spline coefficients fspl(2,j),fspl(3,j), and
    1109              : !  fspl(4,j), j=1 to nx.  The result is a spline s(x) satisfying the
    1110              : !  boundary conditions and with the properties
    1111              : 
    1112              : !     s(x(j)) = fspl(1,j)
    1113              : !     s'(x) is continuous even at the grid points x(j)
    1114              : !     s''(x) is continuous even at the grid points x(j)
    1115              : 
    1116              : !  the formula for evaluation of s(x) is:
    1117              : 
    1118              : !     let dx = x-x(i), where x(i) <= x <= x(i+1).  Then,
    1119              : !     s(x)=fspl(1,i) + dx*(fspl(2,i) +dx*(fspl(3,i) + dx*fspl(4,i)))
    1120              : 
    1121              : !  ==>boundary conditions.  Complete specification of a 1d spline
    1122              : !  requires specification of boundary conditions at x(1) and x(nx).
    1123              : 
    1124              : !  this routine provides 4 options:
    1125              : 
    1126              : ! -1 ***** PERIODIC BC
    1127              : !  ibcxmin=-1  --  periodic boundary condition.  This means the
    1128              : !    boundary conditions s'(x(1))=s'(x(nx)) and s''(x(1))=s''(x(nx))
    1129              : !    are imposed.  Note that s(x(1))=s(x(nx)) (i.e. fspl(1,1)=fspl(1,nx))
    1130              : !    is not required -- that is determined by the fspl array input data.
    1131              : !    The periodic boundary condition is to be preferred for periodic
    1132              : !    data.  When splining periodic data f(x) with period P, the relation
    1133              : !    x(nx)=x(1)+n*P, n = the number of periods (usually 1), should hold.
    1134              : !    (ibcxmax, bcxmin, bcxmax are ignored).
    1135              : 
    1136              : !  if a periodic boundary condition is set, this covers both boundaries.
    1137              : !  for the other types of boundary conditions, the type of condition
    1138              : !  chosen for the x(1) boundary need not be the same as the type chosen
    1139              : !  for the x(nx) boundary.
    1140              : 
    1141              : !  0 ***** NOT A KNOT BC
    1142              : !  ibcxmin=0 | ibcxmax=0 -- this specifies a "not a knot" boundary
    1143              : !    condition -- see cubsplb.for.  This is a common way for inferring
    1144              : !    a "good" spline boundary condition automatically from data in the
    1145              : !    vicinity of the boundary.  (bcxmin | bcxmax are ignored).
    1146              : 
    1147              : !  1 ***** BC:  SPECIFIED SLOPE
    1148              : !  ibcxmin=1 | ibcxmax=1 -- boundary condition is to have s'(x(1)) |
    1149              : !    s'(x(nx)) match the passed value (bcxmin | bcxmax).
    1150              : 
    1151              : !  2 ***** BC:  SPECIFIED 2nd DERIVATIVE
    1152              : !  ibcxmin=2 | ibcxmax=2 -- boundary condition is to have s''(x(1)) |
    1153              : !    s''(x(nx)) match the passed value (bcxmin | bcxmax).
    1154              : 
    1155              : !  3 ***** BC:  SPECIFIED SLOPE = 0.0
    1156              : !  ibcxmin=3 | ibcxmax=3 -- boundary condition is to have s'(x(1)) |
    1157              : !    s'(x(nx)) equal to ZERO.
    1158              : 
    1159              : !  4 ***** BC:  SPECIFIED 2nd DERIVATIVE = 0.0
    1160              : !  ibcxmin=4 | ibcxmax=4 -- boundary condition is to have s''(x(1)) |
    1161              : !    s''(x(nx)) equal to ZERO.
    1162              : 
    1163              : !  5 ***** BC:  1st DIVIDED DIFFERENCE
    1164              : !  ibcxmin=5 | ibcxmax=5 -- boundary condition is to have s'(x(1)) |
    1165              : !    s'(x(nx)) equal to the slope from the 1st|last 2 points
    1166              : 
    1167              : !  6 ***** BC:  2nd DIVIDED DIFFERENCE
    1168              : !  ibcxmin=6 | ibcxmax=6 -- boundary condition is to have s''(x(1)) |
    1169              : !    s''(x(nx)) equal to the 2nd derivative from the 1st|last 3 points
    1170              : 
    1171              : !  7 ***** BC:  3rd DIVIDED DIFFERENCE
    1172              : !  ibcxmin=7 | ibcxmax=7 -- boundary condition is to have s'''(x(1)) |
    1173              : !    s'''(x(nx)) equal to the 3rd derivative from the 1st|last 4 points
    1174              : 
    1175              : !---------------------------------------------------------------------
    1176              :       real(dp), parameter :: half = 0.5d0
    1177              :       real(dp), parameter :: sixth = 1d0/6d0
    1178              :       integer inum,i,ierx
    1179              : 
    1180              : !  error checks
    1181              : 
    1182      6806634 :       ier = 0
    1183      6806634 :       if(nx < 4) then
    1184              : !         write(6,'('' ?cspline:  at least 4 x points required.'')')
    1185            0 :          ier=1
    1186              :       end if
    1187      6806634 :       call ibc_ck_db(ibcxmin,'cspline','xmin',-1,7,ier)
    1188      6806634 :       if(ibcxmin >= 0) call ibc_ck_db(ibcxmax,'cspline','xmax',0,7,ier)
    1189              : 
    1190              : !  x axis check
    1191              : 
    1192      6806634 :       call splinck_db(x,nx,ilinx,1.0d-3,ierx)
    1193      6806634 :       if(ierx /= 0) ier=2
    1194              : 
    1195              : !      if(ier == 2) then
    1196              : !         write(6,'('' ?cspline:  x axis not strict ascending'')')
    1197              : !      end if
    1198              : 
    1199      6806634 :       if(ibcxmin == -1) then
    1200            0 :          inum=nx
    1201            0 :          if(iwk < inum) then
    1202              : !            write(6,1009) inum,iwk,nx
    1203              : ! 1009       format(
    1204              : !     &      ' ?cspline:  workspace too small.  need:  ',i6,' got:  ',i6/
    1205              : !     &      '  (need = nx, nx=',i6)
    1206            0 :             ier=3
    1207              :          end if
    1208              :       end if
    1209              : 
    1210      6806634 :       if(ier /= 0) return
    1211              : 
    1212              : !  OK -- evaluate spline
    1213              : 
    1214      6806634 :       if(ibcxmin == 1) then
    1215            0 :          fspl(2,1)=bcxmin
    1216      6806634 :       else if(ibcxmin == 2) then
    1217            0 :          fspl(3,1)=bcxmin
    1218              :       end if
    1219              : 
    1220      6806634 :       if(ibcxmax == 1) then
    1221            0 :          fspl(2,nx)=bcxmax
    1222      6806634 :       else if(ibcxmax == 2) then
    1223            0 :          fspl(3,nx)=bcxmax
    1224              :       end if
    1225              : 
    1226      6806634 :       call v_spline_db(ibcxmin,ibcxmax,nx,x,fspl,wk)
    1227              : 
    1228   1583109912 :       do i=1,nx
    1229   1576303278 :          fspl(3,i)=half*fspl(3,i)
    1230   1583109912 :          fspl(4,i)=sixth*fspl(4,i)
    1231              :       end do
    1232              : 
    1233              :       return
    1234              :       end subroutine cspline_db
    1235              : 
    1236              : 
    1237            0 :       subroutine evbicub_db(xget,yget,x,nx,y,ny,ilinx,iliny,f1,inf2,ict,fval,ier)
    1238              : 
    1239              : !  use mkbicub to set up spline coefficients!
    1240              : 
    1241              : !  evaluate a 2d cubic Spline interpolant on a rectilinear
    1242              : !  grid -- this is C2 in both directions.
    1243              : 
    1244              : !  this subroutine calls two subroutines:
    1245              : !     herm2xy  -- find cell containing (xget,yget)
    1246              : !     fvbicub  -- evaluate interpolant function and (optionally) derivatives
    1247              : 
    1248              : !  input arguments:
    1249              : !  ================
    1250              : 
    1251              :       implicit none
    1252              :       integer nx,ny                     ! grid sizes
    1253              :       real(dp) xget,yget                    ! target of this interpolation
    1254              :       real(dp) x(nx)                        ! ordered x grid
    1255              :       real(dp) y(ny)                        ! ordered y grid
    1256              :       integer ilinx                     ! ilinx=1 => assume x evenly spaced
    1257              :       integer iliny                     ! iliny=1 => assume y evenly spaced
    1258              : 
    1259              :       integer inf2
    1260              :       real(dp), pointer :: f1(:)
    1261              : 
    1262              : !       f 2nd dimension inf2 must be >= nx
    1263              : !       contents of f:
    1264              : 
    1265              : !  f(0,i,j) = f @ x(i),y(j)
    1266              : !  f(1,i,j) = d2f/dx2 @ x(i),y(j)
    1267              : !  f(2,i,j) = d2f/dy2 @ x(i),y(j)
    1268              : !  f(3,i,j) = d4f/dx2dy2 @ x(i),y(j)
    1269              : 
    1270              : !      (these are spline coefficients selected for continuous 2-
    1271              : !      diffentiability, see mkbicub[w].for)
    1272              : 
    1273              :       integer ict(6)                    ! code specifying output desired
    1274              : 
    1275              : !  ict(1)=1 -- return f  (0, don't)
    1276              : !  ict(2)=1 -- return df/dx  (0, don't)
    1277              : !  ict(3)=1 -- return df/dy  (0, don't)
    1278              : !  ict(4)=1 -- return d2f/dx2  (0, don't)
    1279              : !  ict(5)=1 -- return d2f/dy2  (0, don't)
    1280              : !  ict(6)=1 -- return d2f/dxdy (0, don't)
    1281              : !                   the number of non zero values ict(1:6)
    1282              : !                   determines the number of outputs...
    1283              : 
    1284              : !  new dmc December 2005 -- access to higher derivatives (even if not
    1285              : !  continuous-- but can only go up to 3rd derivatives on any one coordinate.
    1286              : !     if ict(1)=3 -- want 3rd derivatives
    1287              : !          ict(2)=1 for d3f/dx3
    1288              : !          ict(3)=1 for d3f/dx2dy
    1289              : !          ict(4)=1 for d3f/dxdy2
    1290              : !          ict(5)=1 for d3f/dy3
    1291              : !               number of non-zero values ict(2:5) gives no. of outputs
    1292              : !     if ict(1)=4 -- want 4th derivatives
    1293              : !          ict(2)=1 for d4f/dx3dy
    1294              : !          ict(3)=1 for d4f/dx2dy2
    1295              : !          ict(4)=1 for d4f/dxdy3
    1296              : !               number of non-zero values ict(2:4) gives no. of outputs
    1297              : !     if ict(1)=5 -- want 5th derivatives
    1298              : !          ict(2)=1 for d5f/dx3dy2
    1299              : !          ict(3)=1 for d5f/dx2dy3
    1300              : !               number of non-zero values ict(2:3) gives no. of outputs
    1301              : !     if ict(1)=6 -- want 6th derivatives
    1302              : !          d6f/dx3dy3 -- one value is returned.
    1303              : 
    1304              : ! output arguments:
    1305              : ! =================
    1306              : 
    1307              :       real(dp) fval(6)                      ! output data
    1308              :       integer ier                       ! error code =0 ==> no error
    1309              : 
    1310              : !  fval(1) receives the first output (depends on ict(...) spec)
    1311              : !  fval(2) receives the second output (depends on ict(...) spec)
    1312              : !  fval(3) receives the third output (depends on ict(...) spec)
    1313              : !  fval(4) receives the fourth output (depends on ict(...) spec)
    1314              : !  fval(5) receives the fourth output (depends on ict(...) spec)
    1315              : !  fval(6) receives the fourth output (depends on ict(...) spec)
    1316              : 
    1317              : !  examples:
    1318              : !    on input ict = [1,1,1,0,0,1]
    1319              : !   on output fval= [f,df/dx,df/dy,d2f/dxdy], elements 5 & 6 not referenced.
    1320              : 
    1321              : !    on input ict = [1,0,0,0,0,0]
    1322              : !   on output fval= [f] ... elements 2 -- 6 never referenced.
    1323              : 
    1324              : !    on input ict = [0,0,0,1,1,0]
    1325              : !   on output fval= [d2f/dx2,d2f/dy2] ... elements 3 -- 6 never referenced.
    1326              : 
    1327              : !    on input ict = [0,0,1,0,0,0]
    1328              : !   on output fval= [df/dy] ... elements 2 -- 6 never referenced.
    1329              : 
    1330              : !  ier -- completion code:  0 means OK
    1331              : !-------------------
    1332              : !  local:
    1333              : 
    1334              :       integer i,j                       ! cell indices
    1335              : 
    1336              : !  normalized displacement from (x(i),y(j)) corner of cell.
    1337              : !    xparam=0 @x(i)  xparam=1 @x(i+1)
    1338              : !    yparam=0 @y(j)  yparam=1 @y(j+1)
    1339              : 
    1340            0 :       real(dp) xparam,yparam
    1341              : 
    1342              : !  cell dimensions and
    1343              : !  inverse cell dimensions hxi = 1/(x(i+1)-x(i)), hyi = 1/(y(j+1)-y(j))
    1344              : 
    1345            0 :       real(dp) hx,hy
    1346            0 :       real(dp) hxi,hyi
    1347              : 
    1348              : !  0 <= xparam <= 1
    1349              : !  0 <= yparam <= 1
    1350              : 
    1351              : !  ** the interface is very similar to herm2ev.for; can use herm2xy **
    1352              : !---------------------------------------------------------------------
    1353              : 
    1354              :       call herm2xy_db(xget,yget,x,nx,y,ny,ilinx,iliny,
    1355            0 :      &   i,j,xparam,yparam,hx,hxi,hy,hyi,ier)
    1356            0 :       if(ier /= 0) return
    1357              : 
    1358              :       call fvbicub_db(ict,1,1,
    1359              :      &   fval,(/i/),(/j/),(/xparam/),(/yparam/),
    1360            0 :      &   (/hx/),(/hxi/),(/hy/),(/hyi/),f1,inf2,ny)
    1361              : 
    1362            0 :       return
    1363              :       end subroutine evbicub_db
    1364              : 
    1365              : !---------------------------------------------------------------------
    1366              : !  evaluate C1 cubic Hermite function interpolation -- 2d fcn
    1367              : !   --vectorized-- dmc 10 Feb 1999
    1368              : 
    1369              : !  use mkbicub to set up spline coefficients!
    1370              : 
    1371          140 :       subroutine fvbicub_db(ict,ivec,ivecd,
    1372          140 :      &   fval,ii,jj,xparam,yparam,hx,hxi,hy,hyi,
    1373              :      &   f1,inf2,ny)
    1374              : 
    1375              :       integer ict(6)                    ! requested output control
    1376              :       integer ivec                      ! vector length
    1377              :       integer ivecd                     ! vector dimension (1st dim of fval)
    1378              : 
    1379              :       integer ii(ivec),jj(ivec)         ! target cells (i,j)
    1380              :       real(dp) xparam(ivec),yparam(ivec)
    1381              :                           ! normalized displacements from (i,j) corners
    1382              : 
    1383              :       real(dp) hx(ivec),hy(ivec)            ! grid spacing, and
    1384              :       real(dp) hxi(ivec),hyi(ivec)          ! inverse grid spacing 1/(x(i+1)-x(i))
    1385              :                                         ! & 1/(y(j+1)-y(j))
    1386              : 
    1387              :       real(dp), pointer :: f1(:)
    1388              : 
    1389              :       real(dp) fval(ivecd,6)                ! output returned
    1390              : 
    1391              : !  for detailed description of fin, ict and fval see subroutine
    1392              : !  evbicub comments.  Note ict is not vectorized; the same output
    1393              : !  is expected to be returned for all input vector data points.
    1394              : 
    1395              : !  note that the index inputs ii,jj and parameter inputs
    1396              : !     xparam,yparam,hx,hxi,hy,hyi are vectorized, and the
    1397              : !     output array fval has a vector ** 1st dimension ** whose
    1398              : !     size must be given as a separate argument
    1399              : 
    1400              : !  to use this routine in scalar mode, pass in ivec=ivecd=1
    1401              : 
    1402              : C---------------
    1403              : !  Spline evaluation consists of a "mixing" of the interpolant
    1404              : !  data using the linear functionals xparam, xpi = 1-xparam,
    1405              : !  yparam, ypi = 1-yparam, and the cubic functionals
    1406              : !  xparam**3-xparam, xpi**3-xpi, yparam**3-yparam, ypi**3-ypi ...
    1407              : !  and their derivatives as needed.
    1408              : 
    1409              :       integer v
    1410          140 :       real(dp) sum
    1411              : 
    1412              :       real(dp), parameter :: sixth = 1.d0/6.d0
    1413              : 
    1414          140 :       real(dp), pointer :: fin(:,:,:)
    1415          140 :       fin(0:3,1:inf2,1:ny) => f1(1:4*inf2*ny)
    1416              : 
    1417              : C---------------
    1418              : !   ...in x direction
    1419              : 
    1420          140 :       z36th=sixth*sixth
    1421          140 :       iadr=0
    1422              : 
    1423          140 :       if(ict(1) <= 2) then
    1424              : 
    1425              : !  get desired values:
    1426              : 
    1427          140 :          if(ict(1) == 1) then
    1428              : 
    1429              : !  function value:
    1430              : 
    1431          280 :             iadr=iadr+1
    1432          280 :             do v=1,ivec
    1433          140 :                i=ii(v)
    1434          140 :                j=jj(v)
    1435              : 
    1436              : !  in x direction...
    1437              : 
    1438          280 :                xp=xparam(v)
    1439          280 :                xpi=1.d0-xp
    1440          280 :                xp2=xp*xp
    1441          280 :                xpi2=xpi*xpi
    1442              : 
    1443          280 :                cx=xp*(xp2-1.d0)
    1444          280 :                cxi=xpi*(xpi2-1.d0)
    1445          280 :                hx2=hx(v)*hx(v)
    1446              : 
    1447              : !   ...and in y direction
    1448              : 
    1449          280 :                yp=yparam(v)
    1450          280 :                ypi=1.d0-yp
    1451          280 :                yp2=yp*yp
    1452          280 :                ypi2=ypi*ypi
    1453              : 
    1454          280 :                cy=yp*(yp2-1.d0)
    1455          280 :                cyi=ypi*(ypi2-1.d0)
    1456          280 :                hy2=hy(v)*hy(v)
    1457              : 
    1458              :                sum=xpi*(ypi*fin(0,i,j)  +yp*fin(0,i,j+1))+
    1459          140 :      &              xp*(ypi*fin(0,i+1,j)+yp*fin(0,i+1,j+1))
    1460              : 
    1461              :                sum=sum+sixth*hx2*(
    1462              :      &              cxi*(ypi*fin(1,i,j)  +yp*fin(1,i,j+1))+
    1463          140 :      &              cx*(ypi*fin(1,i+1,j)+yp*fin(1,i+1,j+1)))
    1464              : 
    1465              :                sum=sum+sixth*hy2*(
    1466              :      &              xpi*(cyi*fin(2,i,j)  +cy*fin(2,i,j+1))+
    1467          140 :      &              xp*(cyi*fin(2,i+1,j)+cy*fin(2,i+1,j+1)))
    1468              : 
    1469              :                sum=sum+z36th*hx2*hy2*(
    1470              :      &              cxi*(cyi*fin(3,i,j)  +cy*fin(3,i,j+1))+
    1471          140 :      &              cx*(cyi*fin(3,i+1,j)+cy*fin(3,i+1,j+1)))
    1472              : 
    1473          280 :                fval(v,iadr)=sum
    1474              :             end do
    1475              :          end if
    1476              : 
    1477          140 :          if(ict(2) == 1) then
    1478              : 
    1479              : !  df/dx:
    1480              : 
    1481          134 :             iadr=iadr+1
    1482          268 :             do v=1,ivec
    1483          134 :                i=ii(v)
    1484          134 :                j=jj(v)
    1485              : 
    1486              : !  in x direction...
    1487              : 
    1488          134 :                xp=xparam(v)
    1489          134 :                xpi=1.d0-xp
    1490          134 :                xp2=xp*xp
    1491          134 :                xpi2=xpi*xpi
    1492              : 
    1493          274 :                cxd=3.d0*xp2-1.d0
    1494          274 :                cxdi=-3.d0*xpi2+1.d0
    1495              : 
    1496              : !   ...and in y direction
    1497              : 
    1498          134 :                yp=yparam(v)
    1499          134 :                ypi=1.d0-yp
    1500          134 :                yp2=yp*yp
    1501          134 :                ypi2=ypi*ypi
    1502              : 
    1503          134 :                cy=yp*(yp2-1.d0)
    1504          134 :                cyi=ypi*(ypi2-1.d0)
    1505          134 :                hy2=hy(v)*hy(v)
    1506              : 
    1507              :                sum=hxi(v)*(
    1508              :      &              -(ypi*fin(0,i,j)  +yp*fin(0,i,j+1))
    1509          134 :      &              +(ypi*fin(0,i+1,j)+yp*fin(0,i+1,j+1)))
    1510              : 
    1511              :                sum=sum+sixth*hx(v)*(
    1512              :      &              cxdi*(ypi*fin(1,i,j)  +yp*fin(1,i,j+1))+
    1513          134 :      &              cxd*(ypi*fin(1,i+1,j)+yp*fin(1,i+1,j+1)))
    1514              : 
    1515              :                sum=sum+sixth*hxi(v)*hy2*(
    1516              :      &              -(cyi*fin(2,i,j)  +cy*fin(2,i,j+1))
    1517          134 :      &              +(cyi*fin(2,i+1,j)+cy*fin(2,i+1,j+1)))
    1518              : 
    1519              :                sum=sum+z36th*hx(v)*hy2*(
    1520              :      &              cxdi*(cyi*fin(3,i,j)  +cy*fin(3,i,j+1))+
    1521          134 :      &              cxd*(cyi*fin(3,i+1,j)+cy*fin(3,i+1,j+1)))
    1522              : 
    1523          268 :                fval(v,iadr)=sum
    1524              :             end do
    1525              :          end if
    1526              : 
    1527          140 :          if(ict(3) == 1) then
    1528              : 
    1529              : !  df/dy:
    1530              : 
    1531          134 :             iadr=iadr+1
    1532          268 :             do v=1,ivec
    1533          134 :                i=ii(v)
    1534          134 :                j=jj(v)
    1535              : 
    1536              : !  in x direction...
    1537              : 
    1538          134 :                xp=xparam(v)
    1539          134 :                xpi=1.d0-xp
    1540          134 :                xp2=xp*xp
    1541          134 :                xpi2=xpi*xpi
    1542              : 
    1543          134 :                cx=xp*(xp2-1.d0)
    1544          134 :                cxi=xpi*(xpi2-1.d0)
    1545          134 :                hx2=hx(v)*hx(v)
    1546              : 
    1547              : !   ...and in y direction
    1548              : 
    1549          134 :                yp=yparam(v)
    1550          134 :                ypi=1.d0-yp
    1551          134 :                yp2=yp*yp
    1552          134 :                ypi2=ypi*ypi
    1553              : 
    1554          274 :                cyd=3.d0*yp2-1.d0
    1555          274 :                cydi=-3.d0*ypi2+1.d0
    1556              : 
    1557              :                sum=hyi(v)*(
    1558              :      &              xpi*(-fin(0,i,j)  +fin(0,i,j+1))+
    1559          134 :      &              xp*(-fin(0,i+1,j)+fin(0,i+1,j+1)))
    1560              : 
    1561              :                sum=sum+sixth*hx2*hyi(v)*(
    1562              :      &              cxi*(-fin(1,i,j)  +fin(1,i,j+1))+
    1563          134 :      &              cx*(-fin(1,i+1,j)+fin(1,i+1,j+1)))
    1564              : 
    1565              :                sum=sum+sixth*hy(v)*(
    1566              :      &              xpi*(cydi*fin(2,i,j)  +cyd*fin(2,i,j+1))+
    1567          134 :      &              xp*(cydi*fin(2,i+1,j)+cyd*fin(2,i+1,j+1)))
    1568              : 
    1569              :                sum=sum+z36th*hx2*hy(v)*(
    1570              :      &              cxi*(cydi*fin(3,i,j)  +cyd*fin(3,i,j+1))+
    1571          134 :      &              cx*(cydi*fin(3,i+1,j)+cyd*fin(3,i+1,j+1)))
    1572              : 
    1573          268 :                fval(v,iadr)=sum
    1574              :             end do
    1575              :          end if
    1576              : 
    1577          140 :          if(ict(4) == 1) then
    1578              : 
    1579              : !  d2f/dx2:
    1580              : 
    1581            0 :             iadr=iadr+1
    1582            0 :             do v=1,ivec
    1583            0 :                i=ii(v)
    1584            0 :                j=jj(v)
    1585              : 
    1586              : !  in x direction...
    1587              : 
    1588            0 :                xp=xparam(v)
    1589            0 :                xpi=1.d0-xp
    1590              : 
    1591              : !   ...and in y direction
    1592              : 
    1593            0 :                yp=yparam(v)
    1594            0 :                ypi=1.d0-yp
    1595            0 :                yp2=yp*yp
    1596            0 :                ypi2=ypi*ypi
    1597              : 
    1598            0 :                cy=yp*(yp2-1.d0)
    1599            0 :                cyi=ypi*(ypi2-1.d0)
    1600            0 :                hy2=hy(v)*hy(v)
    1601              : 
    1602              :                sum=(
    1603              :      &              xpi*(ypi*fin(1,i,j)  +yp*fin(1,i,j+1))+
    1604            0 :      &              xp*(ypi*fin(1,i+1,j)+yp*fin(1,i+1,j+1)))
    1605              : 
    1606              :                sum=sum+sixth*hy2*(
    1607              :      &              xpi*(cyi*fin(3,i,j)  +cy*fin(3,i,j+1))+
    1608            0 :      &              xp*(cyi*fin(3,i+1,j)+cy*fin(3,i+1,j+1)))
    1609              : 
    1610            0 :                fval(v,iadr)=sum
    1611              :             end do
    1612              :          end if
    1613              : 
    1614          140 :          if(ict(5) == 1) then
    1615              : 
    1616              : !  d2f/dy2:
    1617              : 
    1618            0 :             iadr=iadr+1
    1619            0 :             do v=1,ivec
    1620            0 :                i=ii(v)
    1621            0 :                j=jj(v)
    1622              : 
    1623              : !  in x direction...
    1624              : 
    1625            0 :                xp=xparam(v)
    1626            0 :                xpi=1.d0-xp
    1627            0 :                xp2=xp*xp
    1628            0 :                xpi2=xpi*xpi
    1629              : 
    1630            0 :                cx=xp*(xp2-1.d0)
    1631            0 :                cxi=xpi*(xpi2-1.d0)
    1632            0 :                hx2=hx(v)*hx(v)
    1633              : 
    1634              : !   ...and in y direction
    1635              : 
    1636            0 :                yp=yparam(v)
    1637            0 :                ypi=1.d0-yp
    1638              : 
    1639              :                sum=(
    1640              :      &              xpi*(ypi*fin(2,i,j)  +yp*fin(2,i,j+1))+
    1641            0 :      &              xp*(ypi*fin(2,i+1,j)+yp*fin(2,i+1,j+1)))
    1642              : 
    1643              :                sum=sum+sixth*hx2*(
    1644              :      &              cxi*(ypi*fin(3,i,j)  +yp*fin(3,i,j+1))+
    1645            0 :      &              cx*(ypi*fin(3,i+1,j)+yp*fin(3,i+1,j+1)))
    1646              : 
    1647            0 :                fval(v,iadr)=sum
    1648              :             end do
    1649              :          end if
    1650              : 
    1651          140 :          if(ict(6) == 1) then
    1652              : 
    1653              : !  d2f/dxdy:
    1654              : 
    1655            0 :             iadr=iadr+1
    1656            0 :             do v=1,ivec
    1657            0 :                i=ii(v)
    1658            0 :                j=jj(v)
    1659              : 
    1660              : !  in x direction...
    1661              : 
    1662            0 :                xp=xparam(v)
    1663            0 :                xpi=1.d0-xp
    1664            0 :                xp2=xp*xp
    1665            0 :                xpi2=xpi*xpi
    1666              : 
    1667            0 :                cxd=3.d0*xp2-1.d0
    1668            0 :                cxdi=-3.d0*xpi2+1.d0
    1669              : 
    1670              : !   ...and in y direction
    1671              : 
    1672            0 :                yp=yparam(v)
    1673            0 :                ypi=1.d0-yp
    1674            0 :                yp2=yp*yp
    1675            0 :                ypi2=ypi*ypi
    1676              : 
    1677            0 :                cyd=3.d0*yp2-1.d0
    1678            0 :                cydi=-3.d0*ypi2+1.d0
    1679              : 
    1680              :                sum=hxi(v)*hyi(v)*(
    1681              :      &              fin(0,i,j)  -fin(0,i,j+1)
    1682            0 :      &              -fin(0,i+1,j)+fin(0,i+1,j+1))
    1683              : 
    1684              :                sum=sum+sixth*hx(v)*hyi(v)*(
    1685              :      &              cxdi*(-fin(1,i,j)  +fin(1,i,j+1))+
    1686            0 :      &              cxd*(-fin(1,i+1,j)+fin(1,i+1,j+1)))
    1687              : 
    1688              :                sum=sum+sixth*hxi(v)*hy(v)*(
    1689              :      &              -(cydi*fin(2,i,j)  +cyd*fin(2,i,j+1))
    1690            0 :      &              +(cydi*fin(2,i+1,j)+cyd*fin(2,i+1,j+1)))
    1691              : 
    1692              :                sum=sum+z36th*hx(v)*hy(v)*(
    1693              :      &              cxdi*(cydi*fin(3,i,j)  +cyd*fin(3,i,j+1))+
    1694            0 :      &              cxd*(cydi*fin(3,i+1,j)+cyd*fin(3,i+1,j+1)))
    1695              : 
    1696            0 :                fval(v,iadr)=sum
    1697              :             end do
    1698              :          end if
    1699              : 
    1700              : !-------------------------------------------------
    1701              : 
    1702            0 :       else if(ict(1) == 3) then
    1703            0 :          if(ict(2) == 1) then
    1704              : !  evaluate d3f/dx3 (not continuous)
    1705            0 :             iadr=iadr+1
    1706            0 :             do v=1,ivec
    1707            0 :                i=ii(v)
    1708            0 :                j=jj(v)
    1709            0 :                yp=yparam(v)
    1710            0 :                ypi=1.d0-yp
    1711            0 :                yp2=yp*yp
    1712            0 :                ypi2=ypi*ypi
    1713            0 :                cy=yp*(yp2-1.d0)
    1714            0 :                cyi=ypi*(ypi2-1.d0)
    1715            0 :                hy2=hy(v)*hy(v)
    1716              :                sum=hxi(v)*(
    1717              :      &              -(ypi*fin(1,i,j)  +yp*fin(1,i,j+1))
    1718            0 :      &              +(ypi*fin(1,i+1,j)+yp*fin(1,i+1,j+1)))
    1719              : 
    1720              :                sum=sum+sixth*hy2*hxi(v)*(
    1721              :      &              -(cyi*fin(3,i,j)  +cy*fin(3,i,j+1))
    1722            0 :      &              +(cyi*fin(3,i+1,j)+cy*fin(3,i+1,j+1)))
    1723              : 
    1724            0 :                fval(v,iadr)=sum
    1725              :             end do
    1726              :          end if
    1727              : 
    1728            0 :          if(ict(3) == 1) then
    1729              : !  evaluate d3f/dx2dy
    1730            0 :             iadr=iadr+1
    1731            0 :             do v=1,ivec
    1732            0 :                i=ii(v)
    1733            0 :                j=jj(v)
    1734            0 :                xp=xparam(v)
    1735            0 :                xpi=1.d0-xp
    1736            0 :                yp=yparam(v)
    1737            0 :                ypi=1.d0-yp
    1738            0 :                yp2=yp*yp
    1739            0 :                ypi2=ypi*ypi
    1740            0 :                cyd=3.d0*yp2-1.d0
    1741            0 :                cydi=-3.d0*ypi2+1.d0
    1742              : 
    1743              :                sum=hyi(v)*(
    1744              :      &              xpi*(-fin(1,i,j)  +fin(1,i,j+1))+
    1745            0 :      &              xp*(-fin(1,i+1,j) +fin(1,i+1,j+1)))
    1746              : 
    1747              :                sum=sum+sixth*hy(v)*(
    1748              :      &              xpi*(cydi*fin(3,i,j) +cyd*fin(3,i,j+1))+
    1749            0 :      &              xp*(cydi*fin(3,i+1,j)+cyd*fin(3,i+1,j+1)))
    1750              : 
    1751            0 :                fval(v,iadr)=sum
    1752              :             end do
    1753              :          end if
    1754              : 
    1755            0 :          if(ict(4) == 1) then
    1756              : !  evaluate d3f/dxdy2
    1757            0 :             iadr=iadr+1
    1758            0 :             do v=1,ivec
    1759            0 :                i=ii(v)
    1760            0 :                j=jj(v)
    1761            0 :                xp=xparam(v)
    1762            0 :                xpi=1.d0-xp
    1763            0 :                xp2=xp*xp
    1764            0 :                xpi2=xpi*xpi
    1765            0 :                cxd=3.d0*xp2-1.d0
    1766            0 :                cxdi=-3.d0*xpi2+1.d0
    1767            0 :                yp=yparam(v)
    1768            0 :                ypi=1.d0-yp
    1769              : 
    1770              :                sum=hxi(v)*(
    1771              :      &              -(ypi*fin(2,i,j)  +yp*fin(2,i,j+1))
    1772            0 :      &              +(ypi*fin(2,i+1,j)+yp*fin(2,i+1,j+1)))
    1773              : 
    1774              :                sum=sum+sixth*hx(v)*(
    1775              :      &              cxdi*(ypi*fin(3,i,j)  +yp*fin(3,i,j+1))+
    1776            0 :      &              cxd*(ypi*fin(3,i+1,j)+yp*fin(3,i+1,j+1)))
    1777              : 
    1778            0 :                fval(v,iadr)=sum
    1779              :             end do
    1780              :          end if
    1781              : 
    1782            0 :          if(ict(5) == 1) then
    1783              : !  evaluate d3f/dy3 (not continuous)
    1784            0 :             iadr=iadr+1
    1785            0 :             do v=1,ivec
    1786            0 :                i=ii(v)
    1787            0 :                j=jj(v)
    1788              : 
    1789            0 :                xp=xparam(v)
    1790            0 :                xpi=1.d0-xp
    1791            0 :                xp2=xp*xp
    1792            0 :                xpi2=xpi*xpi
    1793              : 
    1794            0 :                cx=xp*(xp2-1.d0)
    1795            0 :                cxi=xpi*(xpi2-1.d0)
    1796            0 :                hx2=hx(v)*hx(v)
    1797              : 
    1798              :                sum=hyi(v)*(
    1799              :      &              xpi*(-fin(2,i,j)  +fin(2,i,j+1))+
    1800            0 :      &              xp*(-fin(2,i+1,j) +fin(2,i+1,j+1)))
    1801              : 
    1802              :                sum=sum+sixth*hx2*hyi(v)*(
    1803              :      &              cxi*(-fin(3,i,j)  +fin(3,i,j+1))+
    1804            0 :      &              cx*(-fin(3,i+1,j) +fin(3,i+1,j+1)))
    1805              : 
    1806            0 :                fval(v,iadr)=sum
    1807              :             end do
    1808              :          end if
    1809              : 
    1810              : !-----------------------------------
    1811              : !  access to 4th derivatives
    1812              : 
    1813            0 :       else if(ict(1) == 4) then
    1814            0 :          if(ict(2) == 1) then
    1815              : !  evaluate d4f/dx3dy (not continuous)
    1816            0 :             iadr=iadr+1
    1817            0 :             do v=1,ivec
    1818            0 :                i=ii(v)
    1819            0 :                j=jj(v)
    1820            0 :                yp=yparam(v)
    1821            0 :                ypi=1.d0-yp
    1822            0 :                yp2=yp*yp
    1823            0 :                ypi2=ypi*ypi
    1824            0 :                cyd=3.d0*yp2-1.d0
    1825            0 :                cydi=-3.d0*ypi2+1.d0
    1826              : 
    1827              :                sum=hxi(v)*hyi(v)*(
    1828              :      &              +( fin(1,i,j)  -fin(1,i,j+1))
    1829            0 :      &              +(-fin(1,i+1,j)+fin(1,i+1,j+1)))
    1830              : 
    1831              :                sum=sum+sixth*hy(v)*hxi(v)*(
    1832              :      &              -(cydi*fin(3,i,j)  +cyd*fin(3,i,j+1))
    1833            0 :      &              +(cydi*fin(3,i+1,j)+cyd*fin(3,i+1,j+1)))
    1834              : 
    1835            0 :                fval(v,iadr)=sum
    1836              :             end do
    1837              :          end if
    1838              : 
    1839            0 :          if(ict(3) == 1) then
    1840              : !  evaluate d4f/dx2dy2
    1841            0 :             iadr=iadr+1
    1842            0 :             do v=1,ivec
    1843            0 :                i=ii(v)
    1844            0 :                j=jj(v)
    1845              : 
    1846            0 :                xp=xparam(v)
    1847            0 :                xpi=1.d0-xp
    1848            0 :                yp=yparam(v)
    1849            0 :                ypi=1.d0-yp
    1850              : 
    1851              :                sum=xpi*(ypi*fin(3,i,j)  +yp*fin(3,i,j+1))+
    1852            0 :      &              xp*(ypi*fin(3,i+1,j)+yp*fin(3,i+1,j+1))
    1853              : 
    1854            0 :                fval(v,iadr)=sum
    1855              :             end do
    1856              :          end if
    1857              : 
    1858            0 :          if(ict(4) == 1) then
    1859              : !  evaluate d4f/dxdy3 (not continuous)
    1860            0 :             iadr=iadr+1
    1861            0 :             do v=1,ivec
    1862            0 :                i=ii(v)
    1863            0 :                j=jj(v)
    1864              : 
    1865            0 :                xp=xparam(v)
    1866            0 :                xpi=1.d0-xp
    1867            0 :                xp2=xp*xp
    1868            0 :                xpi2=xpi*xpi
    1869              : 
    1870            0 :                cxd=3.d0*xp2-1.d0
    1871            0 :                cxdi=-3.d0*xpi2+1.d0
    1872              : 
    1873              :                sum=hyi(v)*hxi(v)*(
    1874              :      &              +( fin(2,i,j)  -fin(2,i,j+1))
    1875            0 :      &              +(-fin(2,i+1,j)+fin(2,i+1,j+1)))
    1876              : 
    1877              :                sum=sum+sixth*hx(v)*hyi(v)*(
    1878              :      &              cxdi*(-fin(3,i,j)  +fin(3,i,j+1))+
    1879            0 :      &              cxd*(-fin(3,i+1,j) +fin(3,i+1,j+1)))
    1880              : 
    1881            0 :                fval(v,iadr)=sum
    1882              :             end do
    1883              :          end if
    1884              : 
    1885              : !-----------------------------------
    1886              : !  access to 5th derivatives
    1887              : 
    1888            0 :       else if(ict(1) == 5) then
    1889            0 :          if(ict(2) == 1) then
    1890              : !  evaluate d5f/dx3dy2 (not continuous)
    1891            0 :             iadr=iadr+1
    1892            0 :             do v=1,ivec
    1893            0 :                i=ii(v)
    1894            0 :                j=jj(v)
    1895              : 
    1896            0 :                yp=yparam(v)
    1897            0 :                ypi=1.d0-yp
    1898              : 
    1899              :                sum=hxi(v)*(
    1900              :      &              -(ypi*fin(3,i,j)  +yp*fin(3,i,j+1))
    1901            0 :      &              +(ypi*fin(3,i+1,j)+yp*fin(3,i+1,j+1)))
    1902              : 
    1903            0 :                fval(v,iadr)=sum
    1904              :             end do
    1905              :          end if
    1906              : 
    1907            0 :          if(ict(3) == 1) then
    1908              : !  evaluate d5f/dx2dy3 (not continuous)
    1909            0 :             iadr=iadr+1
    1910            0 :             do v=1,ivec
    1911            0 :                i=ii(v)
    1912            0 :                j=jj(v)
    1913              : 
    1914            0 :                xp=xparam(v)
    1915            0 :                xpi=1.d0-xp
    1916              : 
    1917              :                sum=hyi(v)*(
    1918              :      &              xpi*(-fin(3,i,j)  +fin(3,i,j+1))+
    1919            0 :      &              xp*(-fin(3,i+1,j)+fin(3,i+1,j+1)))
    1920              : 
    1921            0 :                fval(v,iadr)=sum
    1922              :             end do
    1923              :          end if
    1924              : 
    1925              : !-----------------------------------
    1926              : !  access to 6th derivatives
    1927              : 
    1928            0 :       else if(ict(1) == 6) then
    1929              : !  evaluate d6f/dx3dy3 (not continuous)
    1930            0 :          iadr=iadr+1
    1931            0 :          do v=1,ivec
    1932            0 :             i=ii(v)
    1933            0 :             j=jj(v)
    1934              :             sum=hxi(v)*hyi(v)*(
    1935              :      &              +( fin(3,i,j)  -fin(3,i,j+1))
    1936            0 :      &              +(-fin(3,i+1,j)+fin(3,i+1,j+1)))
    1937            0 :             fval(v,iadr)=sum
    1938              :          end do
    1939              :       end if
    1940              : 
    1941          140 :       return
    1942          140 :       end subroutine fvbicub_db
    1943              : 
    1944              : 
    1945            0 :       subroutine herm2ev_db(xget,yget,x,nx,y,ny,ilinx,iliny,f,inf2,ict,fval,ier)
    1946              : 
    1947              : !  evaluate a 2d cubic Hermite interpolant on a rectilinear
    1948              : !  grid -- this is C1 in both directions.
    1949              : 
    1950              : !  this subroutine calls two subroutines:
    1951              : !     herm2xy  -- find cell containing (xget,yget)
    1952              : !     herm2fcn -- evaluate interpolant function and (optionally) derivatives
    1953              : 
    1954              : !  input arguments:
    1955              : !  ================
    1956              : 
    1957              :       real(dp) xget,yget                    ! target of this interpolation
    1958              :       real(dp) x(nx)                        ! ordered x grid
    1959              :       real(dp) y(ny)                        ! ordered y grid
    1960              :       integer ilinx                     ! ilinx=1 => assume x evenly spaced
    1961              :       integer iliny                     ! iliny=1 => assume y evenly spaced
    1962              : 
    1963              :       real(dp) f(0:3,inf2,ny)               ! function data
    1964              : 
    1965              : !       f 2nd dimension inf2 must be >= nx
    1966              : !       contents of f:
    1967              : 
    1968              : !  f(0,i,j) = f @ x(i),y(j)
    1969              : !  f(1,i,j) = df/dx @ x(i),y(j)
    1970              : !  f(2,i,j) = df/dy @ x(i),y(j)
    1971              : !  f(3,i,j) = d2f/dxdy @ x(i),y(j)
    1972              : 
    1973              :       integer ict(4)                    ! code specifying output desired
    1974              : 
    1975              : !  ict(1)=1 -- return f  (0, don't)
    1976              : !  ict(2)=1 -- return df/dx  (0, don't)
    1977              : !  ict(3)=1 -- return df/dy  (0, don't)
    1978              : !  ict(4)=1 -- return d2f/dxdy (0, don't)
    1979              : 
    1980              : ! output arguments:
    1981              : ! =================
    1982              : 
    1983              :       real(dp) fval(4)                      ! output data
    1984              :       integer ier                       ! error code =0 ==> no error
    1985              : 
    1986              : !  fval(1) receives the first output (depends on ict(...) spec)
    1987              : !  fval(2) receives the second output (depends on ict(...) spec)
    1988              : !  fval(3) receives the third output (depends on ict(...) spec)
    1989              : !  fval(4) receives the fourth output (depends on ict(...) spec)
    1990              : 
    1991              : !  examples:
    1992              : !    on input ict = [1,1,1,1]
    1993              : !   on output fval= [f,df/dx,df/dy,d2f/dxdy]
    1994              : 
    1995              : !    on input ict = [1,0,0,0]
    1996              : !   on output fval= [f] ... elements 2 & 3 & 4 never referenced
    1997              : 
    1998              : !    on input ict = [0,1,1,0]
    1999              : !   on output fval= [df/dx,df/dy] ... element 3 & 4 never referenced
    2000              : 
    2001              : !    on input ict = [0,0,1,0]
    2002              : !   on output fval= [df/dy] ... elements 2 & 3 & 4 never referenced.
    2003              : 
    2004              : !  ier -- completion code:  0 means OK
    2005              : !-------------------
    2006              : !  local:
    2007              : 
    2008              :       integer i,j                       ! cell indices
    2009              : 
    2010              : !  normalized displacement from (x(i),y(j)) corner of cell.
    2011              : !    xparam=0 @x(i)  xparam=1 @x(i+1)
    2012              : !    yparam=0 @y(j)  yparam=1 @y(j+1)
    2013              : 
    2014            0 :       real(dp) xparam,yparam
    2015              : 
    2016              : !  cell dimensions and
    2017              : !  inverse cell dimensions hxi = 1/(x(i+1)-x(i)), hyi = 1/(y(j+1)-y(j))
    2018              : 
    2019            0 :       real(dp) hx,hy
    2020            0 :       real(dp) hxi,hyi
    2021              : 
    2022              : !  0 <= xparam <= 1
    2023              : !  0 <= yparam <= 1
    2024              : 
    2025              : !---------------------------------------------------------------------
    2026              : 
    2027              :       call herm2xy_db(xget,yget,x,nx,y,ny,ilinx,iliny,
    2028            0 :      &   i,j,xparam,yparam,hx,hxi,hy,hyi,ier)
    2029            0 :       if(ier /= 0) return
    2030              : 
    2031              :       call herm2fcn_db(ict,1,1,
    2032              :      &   fval,(/i/),(/j/),(/xparam/),(/yparam/),
    2033            0 :      &   (/hx/),(/hxi/),(/hy/),(/hyi/),f,inf2,ny)
    2034              : 
    2035            0 :       return
    2036              :       end subroutine herm2ev_db
    2037              : 
    2038              : !---------------------------------------------------------------------
    2039              : !  herm2xy -- look up x-y zone
    2040              : 
    2041              : !  this is the "first part" of herm2ev, see comments, above.
    2042              : 
    2043          140 :       subroutine herm2xy_db(xget,yget,x,nx,y,ny,ilinx,iliny,
    2044              :      &   i,j,xparam,yparam,hx,hxi,hy,hyi,ier)
    2045              : 
    2046              : !  input of herm2xy
    2047              : !  ================
    2048              :       implicit none
    2049              : 
    2050              :       integer nx,ny                     ! array dimensions
    2051              : 
    2052              :       real(dp) xget,yget                    ! target point
    2053              :       real(dp) x(:) ! (nx)                  ! indep. coords., strict ascending
    2054              :       real(dp) y(:) ! (ny)                  ! indep. coords., strict ascending
    2055              : 
    2056              :       integer ilinx                     ! =1:  x evenly spaced
    2057              :       integer iliny                     ! =1:  y evenly spaced
    2058              : 
    2059              : !  output of herm2xy
    2060              : !  =================
    2061              :       integer i,j                       ! index to cell containing target pt
    2062              : !          on exit:  1 <= i <= nx-1   1 <= j <= ny-1
    2063              : 
    2064              : !  normalized position w/in (i,j) cell (btw 0 and 1):
    2065              : 
    2066              :       real(dp) xparam                       ! (xget-x(i))/(x(i+1)-x(i))
    2067              :       real(dp) yparam                       ! (yget-y(j))/(y(j+1)-y(j))
    2068              : 
    2069              : !  grid spacing
    2070              : 
    2071              :       real(dp) hx                           ! hx = x(i+1)-x(i)
    2072              :       real(dp) hy                           ! hy = y(j+1)-y(j)
    2073              : 
    2074              : !  inverse grid spacing:
    2075              : 
    2076              :       real(dp) hxi                          ! 1/hx = 1/(x(i+1)-x(i))
    2077              :       real(dp) hyi                          ! 1/hy = 1/(y(j+1)-y(j))
    2078              : 
    2079              :       integer ier                       ! return ier /= 0 on error
    2080              : 
    2081              : !------------------------------------
    2082          140 :       real(dp) zxget,zyget,zxtol,zytol
    2083              :       integer nxm,nym,ii,jj
    2084              : 
    2085              : 
    2086          140 :       ier=0
    2087              : 
    2088              : !  range check
    2089              : 
    2090          140 :       zxget=xget
    2091          140 :       zyget=yget
    2092          140 :       if((xget < x(1)).or.(xget > x(nx))) then
    2093            0 :          zxtol=4.0d-7*max(abs(x(1)),abs(x(nx)))
    2094            0 :          if((xget < x(1)-zxtol).or.(xget > x(nx)+zxtol)) then
    2095            0 :             ier=1
    2096              :             !write(6,1001) xget,x(1),x(nx)
    2097              : ! 1001       format(' ?herm2ev:  xget=',1pe11.4,' out of range ', 1pe11.4,' to ',1pe11.4)
    2098              :          else
    2099              :             !if((xget < x(1)-0.5*zxtol).or.(xget > x(nx)+0.5*zxtol)) write(6,1011) xget,x(1),x(nx)
    2100              : ! 1011       format(' %herm2ev:  xget=',1pe15.8,' beyond range ', 1pe15.8,' to ',1pe15.8,' (fixup applied)')
    2101            0 :             if(xget < x(1)) then
    2102            0 :                zxget=x(1)
    2103              :             else
    2104            0 :                zxget=x(nx)
    2105              :             end if
    2106              :          end if
    2107              :       end if
    2108          140 :       if((yget < y(1)).or.(yget > y(ny))) then
    2109            0 :          zytol=4.0d-7*max(abs(y(1)),abs(y(ny)))
    2110            0 :          if((yget < y(1)-zytol).or.(yget > y(ny)+zytol)) then
    2111            0 :             ier=1
    2112              : !            write(6,1002) yget,y(1),y(ny)
    2113              : ! 1002       format(' ?herm2ev:  yget=',1pe11.4,' out of range ', 1pe11.4,' to ',1pe11.4)
    2114              :          else
    2115              : !            if((yget < y(1)-0.5*zytol).or. (yget > y(ny)+0.5*zytol)) write(6,1012) yget,y(1),y(ny)
    2116              : ! 1012       format(' %herm2ev:  yget=',1pe15.8,' beyond range ', 1pe15.8,' to ',1pe15.8,' (fixup applied)')
    2117            0 :             if(yget < y(1)) then
    2118            0 :                zyget=y(1)
    2119              :             else
    2120            0 :                zyget=y(ny)
    2121              :             end if
    2122              :          end if
    2123              :       end if
    2124          140 :       if(ier /= 0) return
    2125              : 
    2126              : !  now find interval in which target point lies..
    2127              : 
    2128          140 :       nxm=nx-1
    2129          140 :       nym=ny-1
    2130              : 
    2131          140 :       if(ilinx == 1) then
    2132          134 :          ii=1+nxm*(zxget-x(1))/(x(nx)-x(1))
    2133          134 :          i=min(nxm, ii)
    2134          134 :          if(zxget < x(i)) then
    2135            0 :             i=i-1
    2136          134 :          else if(zxget > x(i+1)) then
    2137            0 :             i=i+1
    2138              :          end if
    2139              :       else
    2140            6 :          if((1 <= i).and.(i < nxm)) then
    2141            4 :             if((x(i) <= zxget).and.(zxget <= x(i+1))) then
    2142              :                continue  ! already have the zone
    2143              :             else
    2144            4 :                call zonfind_db(x,nx,zxget,i)
    2145              :             end if
    2146              :          else
    2147            2 :             call zonfind_db(x,nx,zxget,i)
    2148              :          end if
    2149              :       end if
    2150              : 
    2151          140 :       if(iliny == 1) then
    2152           20 :          jj=1+nym*(zyget-y(1))/(y(ny)-y(1))
    2153           20 :          j=min(nym, jj)
    2154           20 :          if(zyget < y(j)) then
    2155            0 :             j=j-1
    2156           20 :          else if(zyget > y(j+1)) then
    2157            0 :             j=j+1
    2158              :          end if
    2159              :       else
    2160          120 :          if((1 <= j).and.(j < nym)) then
    2161          102 :             if((y(j) <= zyget).and.(zyget <= y(j+1))) then
    2162              :                continue  ! already have the zone
    2163              :             else
    2164            0 :                call zonfind_db(y,ny,zyget,j)
    2165              :             end if
    2166              :          else
    2167           18 :             call zonfind_db(y,ny,zyget,j)
    2168              :          end if
    2169              :       end if
    2170              : 
    2171          140 :       hx=(x(i+1)-x(i))
    2172          140 :       hy=(y(j+1)-y(j))
    2173              : 
    2174          140 :       hxi=1.d0/hx
    2175          140 :       hyi=1.d0/hy
    2176              : 
    2177          140 :       xparam=(zxget-x(i))*hxi
    2178          140 :       yparam=(zyget-y(j))*hyi
    2179              : 
    2180          140 :       return
    2181              :       end subroutine herm2xy_db
    2182              : 
    2183              : 
    2184              : !---------------------------------------------------------------------
    2185              : !  evaluate C1 cubic Hermite function interpolation -- 2d fcn
    2186              : !   --vectorized-- dmc 10 Feb 1999
    2187              : 
    2188            0 :       subroutine herm2fcn_db(ict,ivec,ivecd,
    2189            0 :      &   fval,ii,jj,xparam,yparam,hx,hxi,hy,hyi,
    2190            0 :      &   fin,inf2,ny)
    2191              : 
    2192              :       integer ict(4)                    ! requested output control
    2193              :       integer ivec                      ! vector length
    2194              :       integer ivecd                     ! vector dimension (1st dim of fval)
    2195              : 
    2196              :       integer ii(ivec),jj(ivec)         ! target cells (i,j)
    2197              :       real(dp) xparam(ivec),yparam(ivec)
    2198              :                           ! normalized displacements from (i,j) corners
    2199              : 
    2200              :       real(dp) hx(ivec),hy(ivec)            ! grid spacing, and
    2201              :       real(dp) hxi(ivec),hyi(ivec)          ! inverse grid spacing 1/(x(i+1)-x(i))
    2202              :                                         ! & 1/(y(j+1)-y(j))
    2203              : 
    2204              :       real(dp) fin(0:3,inf2,ny)             ! interpolant data (cf "herm2ev")
    2205              : 
    2206              :       real(dp) fval(ivecd,4)                ! output returned
    2207              : 
    2208              : !  for detailed description of fin, ict and fval see subroutine
    2209              : !  herm2ev comments.  Note ict is not vectorized; the same output
    2210              : !  is expected to be returned for all input vector data points.
    2211              : 
    2212              : !  note that the index inputs ii,jj and parameter inputs
    2213              : !     xparam,yparam,hx,hxi,hy,hyi are vectorized, and the
    2214              : !     output array fval has a vector ** 1st dimension ** whose
    2215              : !     size must be given as a separate argument
    2216              : 
    2217              : !  to use this routine in scalar mode, pass in ivec=ivecd=1
    2218              : 
    2219              : !---------------
    2220              : !  Hermite cubic basis functions
    2221              : !  -->for function value matching
    2222              : !     a(0)=0 a(1)=1        a'(0)=0 a'(1)=0
    2223              : !   abar(0)=1 abar(1)=0  abar'(0)=0 abar'(1)=0
    2224              : 
    2225              : !   a(x)=-2*x**3 + 3*x**2    = x*x*(-2.d0*x+3.0)
    2226              : !   abar(x)=1-a(x)
    2227              : !   a'(x)=-abar'(x)          = 6.d0*x*(1.0-x)
    2228              : 
    2229              : !  -->for derivative matching
    2230              : !     b(0)=0 b(1)=0          b'(0)=0 b'(1)=1
    2231              : !   bbar(0)=0 bbar(1)=0  bbar'(0)=1 bbar'(1)=0
    2232              : 
    2233              : !     b(x)=x**3-x**2         b'(x)=3*x**2-2*x
    2234              : !     bbar(x)=x**3-2*x**2+x  bbar'(x)=3*x**2-4*x+1
    2235              : 
    2236            0 :       real(dp) sum
    2237              :       integer v
    2238              : 
    2239            0 :       do v=1,ivec
    2240            0 :          i=ii(v)
    2241            0 :          j=jj(v)
    2242              : 
    2243              : !   ...in x direction
    2244              : 
    2245            0 :          xp=xparam(v)
    2246            0 :          xpi=1.d0-xp
    2247            0 :          xp2=xp*xp
    2248            0 :          xpi2=xpi*xpi
    2249            0 :          ax=xp2*(3.d0-2.d0*xp)
    2250            0 :          axbar=1.d0-ax
    2251            0 :          bx=-xp2*xpi
    2252            0 :          bxbar=xpi2*xp
    2253              : 
    2254              : !   ...in y direction
    2255              : 
    2256            0 :          yp=yparam(v)
    2257            0 :          ypi=1.d0-yp
    2258            0 :          yp2=yp*yp
    2259            0 :          ypi2=ypi*ypi
    2260            0 :          ay=yp2*(3.d0-2.d0*yp)
    2261            0 :          aybar=1.d0-ay
    2262            0 :          by=-yp2*ypi
    2263            0 :          bybar=ypi2*yp
    2264              : 
    2265              : !   ...derivatives...
    2266              : 
    2267            0 :          axp=6.d0*xp*xpi
    2268            0 :          axbarp=-axp
    2269            0 :          bxp=xp*(3.d0*xp-2.d0)
    2270            0 :          bxbarp=xpi*(3.d0*xpi-2.d0)
    2271              : 
    2272            0 :          ayp=6.d0*yp*ypi
    2273            0 :          aybarp=-ayp
    2274            0 :          byp=yp*(3.d0*yp-2.d0)
    2275            0 :          bybarp=ypi*(3.d0*ypi-2.d0)
    2276              : 
    2277            0 :          iadr=0
    2278              : 
    2279              : !  get desired values:
    2280              : 
    2281            0 :          if(ict(1) == 1) then
    2282              : 
    2283              : !  function value:
    2284              : 
    2285            0 :             iadr=iadr+1
    2286              :             sum=axbar*(aybar*fin(0,i,j)  +ay*fin(0,i,j+1))+
    2287            0 :      &             ax*(aybar*fin(0,i+1,j)+ay*fin(0,i+1,j+1))
    2288              : 
    2289              :             sum=sum+hx(v)*(
    2290              :      &         bxbar*(aybar*fin(1,i,j)  +ay*fin(1,i,j+1))+
    2291            0 :      &            bx*(aybar*fin(1,i+1,j)+ay*fin(1,i+1,j+1)))
    2292              : 
    2293              :             sum=sum+hy(v)*(
    2294              :      &         axbar*(bybar*fin(2,i,j)  +by*fin(2,i,j+1))+
    2295            0 :      &            ax*(bybar*fin(2,i+1,j)+by*fin(2,i+1,j+1)))
    2296              : 
    2297              :             sum=sum+hx(v)*hy(v)*(
    2298              :      &         bxbar*(bybar*fin(3,i,j)  +by*fin(3,i,j+1))+
    2299            0 :      &            bx*(bybar*fin(3,i+1,j)+by*fin(3,i+1,j+1)))
    2300              : 
    2301            0 :             fval(v,iadr)=sum
    2302              :          end if
    2303              : 
    2304            0 :          if(ict(2) == 1) then
    2305              : 
    2306              : !  df/dx:
    2307              : 
    2308            0 :             iadr=iadr+1
    2309              : 
    2310              :             sum=hxi(v)*(
    2311              :      &         axbarp*(aybar*fin(0,i,j)  +ay*fin(0,i,j+1))+
    2312            0 :      &            axp*(aybar*fin(0,i+1,j)+ay*fin(0,i+1,j+1)))
    2313              : 
    2314              :             sum=sum+
    2315              :      &         bxbarp*(aybar*fin(1,i,j)  +ay*fin(1,i,j+1))+
    2316            0 :      &            bxp*(aybar*fin(1,i+1,j)+ay*fin(1,i+1,j+1))
    2317              : 
    2318              :             sum=sum+hxi(v)*hy(v)*(
    2319              :      &         axbarp*(bybar*fin(2,i,j)  +by*fin(2,i,j+1))+
    2320            0 :      &            axp*(bybar*fin(2,i+1,j)+by*fin(2,i+1,j+1)))
    2321              : 
    2322              :             sum=sum+hy(v)*(
    2323              :      &         bxbarp*(bybar*fin(3,i,j)  +by*fin(3,i,j+1))+
    2324            0 :      &            bxp*(bybar*fin(3,i+1,j)+by*fin(3,i+1,j+1)))
    2325              : 
    2326            0 :             fval(v,iadr)=sum
    2327              :          end if
    2328              : 
    2329            0 :          if(ict(3) == 1) then
    2330              : 
    2331              : !  df/dy:
    2332              : 
    2333            0 :             iadr=iadr+1
    2334              : 
    2335              :             sum=hyi(v)*(
    2336              :      &         axbar*(aybarp*fin(0,i,j)  +ayp*fin(0,i,j+1))+
    2337            0 :      &            ax*(aybarp*fin(0,i+1,j)+ayp*fin(0,i+1,j+1)))
    2338              : 
    2339              :             sum=sum+hx(v)*hyi(v)*(
    2340              :      &         bxbar*(aybarp*fin(1,i,j)  +ayp*fin(1,i,j+1))+
    2341            0 :      &            bx*(aybarp*fin(1,i+1,j)+ayp*fin(1,i+1,j+1)))
    2342              : 
    2343              :             sum=sum+
    2344              :      &         axbar*(bybarp*fin(2,i,j)  +byp*fin(2,i,j+1))+
    2345            0 :      &            ax*(bybarp*fin(2,i+1,j)+byp*fin(2,i+1,j+1))
    2346              : 
    2347              :             sum=sum+hx(v)*(
    2348              :      &         bxbar*(bybarp*fin(3,i,j)  +byp*fin(3,i,j+1))+
    2349            0 :      &            bx*(bybarp*fin(3,i+1,j)+byp*fin(3,i+1,j+1)))
    2350              : 
    2351            0 :             fval(v,iadr)=sum
    2352              :          end if
    2353              : 
    2354            0 :          if(ict(4) == 1) then
    2355              : 
    2356              : !  d2f/dxdy:
    2357              : 
    2358            0 :             iadr=iadr+1
    2359              : 
    2360              :             sum=hxi(v)*hyi(v)*(
    2361              :      &         axbarp*(aybarp*fin(0,i,j)  +ayp*fin(0,i,j+1))+
    2362            0 :      &            axp*(aybarp*fin(0,i+1,j)+ayp*fin(0,i+1,j+1)))
    2363              : 
    2364              :             sum=sum+hyi(v)*(
    2365              :      &         bxbarp*(aybarp*fin(1,i,j)  +ayp*fin(1,i,j+1))+
    2366            0 :      &            bxp*(aybarp*fin(1,i+1,j)+ayp*fin(1,i+1,j+1)))
    2367              : 
    2368              :             sum=sum+hxi(v)*(
    2369              :      &         axbarp*(bybarp*fin(2,i,j)  +byp*fin(2,i,j+1))+
    2370            0 :      &            axp*(bybarp*fin(2,i+1,j)+byp*fin(2,i+1,j+1)))
    2371              : 
    2372              :             sum=sum+
    2373              :      &         bxbarp*(bybarp*fin(3,i,j)  +byp*fin(3,i,j+1))+
    2374            0 :      &            bxp*(bybarp*fin(3,i+1,j)+byp*fin(3,i+1,j+1))
    2375              : 
    2376            0 :             fval(v,iadr)=sum
    2377              :          end if
    2378              : 
    2379              :       end do                             ! vector loop
    2380              : 
    2381            0 :       return
    2382              :       end subroutine herm2fcn_db
    2383              : 
    2384              : 
    2385              : !---------------------------------------------------------------------
    2386              : !  evaluate C1 cubic Hermite function interpolation -- 2d fcn
    2387              : !   --vectorized-- dmc 10 Feb 1999
    2388              : 
    2389            0 :       subroutine herm2fcn_mesa_db(ict,ivec,ivecd,
    2390            0 :      &   fval,ii,jj,xparam,yparam,hx,hxi,hy,hyi,
    2391              :      &   f1,inf2,ny)
    2392              : 
    2393              :       integer ny, inf2
    2394              :       integer ict(4)                    ! requested output control
    2395              :       integer ivec                      ! vector length
    2396              :       integer ivecd                     ! vector dimension (1st dim of fval)
    2397              : 
    2398              :       integer ii(ivec),jj(ivec)         ! target cells (i,j)
    2399              :       real(dp) :: xparam(ivec),yparam(ivec)
    2400              :                           ! normalized displacements from (i,j) corners
    2401              : 
    2402              :       real(dp) :: hx(ivec),hy(ivec)            ! grid spacing, and
    2403              :       real(dp) :: hxi(ivec),hyi(ivec)          ! inverse grid spacing 1/(x(i+1)-x(i))
    2404              :                                         ! & 1/(y(j+1)-y(j))
    2405              : 
    2406              :       real(dp), pointer :: f1(:) ! =(0:3,inf2,ny)  interpolant data (cf "evbicub")
    2407              : 
    2408              :       real(dp) :: fval(ivecd,4)                ! output returned
    2409              : 
    2410              : !  for detailed description of fin, ict and fval see subroutine
    2411              : !  herm2ev comments.  Note ict is not vectorized; the same output
    2412              : !  is expected to be returned for all input vector data points.
    2413              : 
    2414              : !  note that the index inputs ii,jj and parameter inputs
    2415              : !     xparam,yparam,hx,hxi,hy,hyi are vectorized, and the
    2416              : !     output array fval has a vector ** 1st dimension ** whose
    2417              : !     size must be given as a separate argument
    2418              : 
    2419              : !  to use this routine in scalar mode, pass in ivec=ivecd=1
    2420              : 
    2421              : !---------------
    2422              : !  Hermite cubic basis functions
    2423              : !  -->for function value matching
    2424              : !     a(0)=0 a(1)=1        a'(0)=0 a'(1)=0
    2425              : !   abar(0)=1 abar(1)=0  abar'(0)=0 abar'(1)=0
    2426              : 
    2427              : !   a(x)=-2*x**3 + 3*x**2    = x*x*(-2.d0*x+3.0)
    2428              : !   abar(x)=1-a(x)
    2429              : !   a'(x)=-abar'(x)          = 6.d0*x*(1.0-x)
    2430              : 
    2431              : !  -->for derivative matching
    2432              : !     b(0)=0 b(1)=0          b'(0)=0 b'(1)=1
    2433              : !   bbar(0)=0 bbar(1)=0  bbar'(0)=1 bbar'(1)=0
    2434              : 
    2435              : !     b(x)=x**3-x**2         b'(x)=3*x**2-2*x
    2436              : !     bbar(x)=x**3-2*x**2+x  bbar'(x)=3*x**2-4*x+1
    2437              : 
    2438            0 :       real(dp) :: sum
    2439              :       integer v,iadr,i,j
    2440            0 :       real(dp) :: xp,yp,xpi,ypi,xp2,yp2,xpi2,ypi2
    2441            0 :       real(dp) :: ax,bx,axbar,bxbar,ay,by,aybar,bybar
    2442            0 :       real(dp) :: axp,axbarp,bxp,bxbarp,ayp,aybarp,bybarp,byp
    2443            0 :       real(dp), pointer :: fin(:,:,:)
    2444              : 
    2445            0 :       fin(0:3,1:inf2,1:ny) => f1(1:4*inf2*ny)
    2446              : 
    2447            0 :       do v=1,ivec
    2448            0 :          i=ii(v)
    2449            0 :          j=jj(v)
    2450              : 
    2451              : !   ...in x direction
    2452              : 
    2453            0 :          xp=xparam(v)
    2454            0 :          xpi=1.d0-xp
    2455            0 :          xp2=xp*xp
    2456            0 :          xpi2=xpi*xpi
    2457            0 :          ax=xp2*(3.d0-2.d0*xp)
    2458            0 :          axbar=1.d0-ax
    2459            0 :          bx=-xp2*xpi
    2460            0 :          bxbar=xpi2*xp
    2461              : 
    2462              : !   ...in y direction
    2463              : 
    2464            0 :          yp=yparam(v)
    2465            0 :          ypi=1.d0-yp
    2466            0 :          yp2=yp*yp
    2467            0 :          ypi2=ypi*ypi
    2468            0 :          ay=yp2*(3.d0-2.d0*yp)
    2469            0 :          aybar=1.d0-ay
    2470            0 :          by=-yp2*ypi
    2471            0 :          bybar=ypi2*yp
    2472              : 
    2473              : !   ...derivatives...
    2474              : 
    2475            0 :          axp=6.d0*xp*xpi
    2476            0 :          axbarp=-axp
    2477            0 :          bxp=xp*(3.d0*xp-2.d0)
    2478            0 :          bxbarp=xpi*(3.d0*xpi-2.d0)
    2479              : 
    2480            0 :          ayp=6.d0*yp*ypi
    2481            0 :          aybarp=-ayp
    2482            0 :          byp=yp*(3.d0*yp-2.d0)
    2483            0 :          bybarp=ypi*(3.d0*ypi-2.d0)
    2484              : 
    2485            0 :          iadr=0
    2486              : 
    2487              : !  get desired values:
    2488              : 
    2489            0 :          if(ict(1) == 1) then
    2490              : 
    2491              : !  function value:
    2492              : 
    2493            0 :             iadr=iadr+1
    2494              :             sum=axbar*(aybar*fin(0,i,j)  +ay*fin(0,i,j+1))+
    2495            0 :      &             ax*(aybar*fin(0,i+1,j)+ay*fin(0,i+1,j+1))
    2496              : 
    2497              :             sum=sum+hx(v)*(
    2498              :      &         bxbar*(aybar*fin(1,i,j)  +ay*fin(1,i,j+1))+
    2499            0 :      &            bx*(aybar*fin(1,i+1,j)+ay*fin(1,i+1,j+1)))
    2500              : 
    2501              :             sum=sum+hy(v)*(
    2502              :      &         axbar*(bybar*fin(2,i,j)  +by*fin(2,i,j+1))+
    2503            0 :      &            ax*(bybar*fin(2,i+1,j)+by*fin(2,i+1,j+1)))
    2504              : 
    2505              :             sum=sum+hx(v)*hy(v)*(
    2506              :      &         bxbar*(bybar*fin(3,i,j)  +by*fin(3,i,j+1))+
    2507            0 :      &            bx*(bybar*fin(3,i+1,j)+by*fin(3,i+1,j+1)))
    2508              : 
    2509            0 :             fval(v,iadr)=sum
    2510              :          end if
    2511              : 
    2512            0 :          if(ict(2) == 1) then
    2513              : 
    2514              : !  df/dx:
    2515              : 
    2516            0 :             iadr=iadr+1
    2517              : 
    2518              :             sum=hxi(v)*(
    2519              :      &         axbarp*(aybar*fin(0,i,j)  +ay*fin(0,i,j+1))+
    2520            0 :      &            axp*(aybar*fin(0,i+1,j)+ay*fin(0,i+1,j+1)))
    2521              : 
    2522              :             sum=sum+
    2523              :      &         bxbarp*(aybar*fin(1,i,j)  +ay*fin(1,i,j+1))+
    2524            0 :      &            bxp*(aybar*fin(1,i+1,j)+ay*fin(1,i+1,j+1))
    2525              : 
    2526              :             sum=sum+hxi(v)*hy(v)*(
    2527              :      &         axbarp*(bybar*fin(2,i,j)  +by*fin(2,i,j+1))+
    2528            0 :      &            axp*(bybar*fin(2,i+1,j)+by*fin(2,i+1,j+1)))
    2529              : 
    2530              :             sum=sum+hy(v)*(
    2531              :      &         bxbarp*(bybar*fin(3,i,j)  +by*fin(3,i,j+1))+
    2532            0 :      &            bxp*(bybar*fin(3,i+1,j)+by*fin(3,i+1,j+1)))
    2533              : 
    2534            0 :             fval(v,iadr)=sum
    2535              :          end if
    2536              : 
    2537            0 :          if(ict(3) == 1) then
    2538              : 
    2539              : !  df/dy:
    2540              : 
    2541            0 :             iadr=iadr+1
    2542              : 
    2543              :             sum=hyi(v)*(
    2544              :      &         axbar*(aybarp*fin(0,i,j)  +ayp*fin(0,i,j+1))+
    2545            0 :      &            ax*(aybarp*fin(0,i+1,j)+ayp*fin(0,i+1,j+1)))
    2546              : 
    2547              :             sum=sum+hx(v)*hyi(v)*(
    2548              :      &         bxbar*(aybarp*fin(1,i,j)  +ayp*fin(1,i,j+1))+
    2549            0 :      &            bx*(aybarp*fin(1,i+1,j)+ayp*fin(1,i+1,j+1)))
    2550              : 
    2551              :             sum=sum+
    2552              :      &         axbar*(bybarp*fin(2,i,j)  +byp*fin(2,i,j+1))+
    2553            0 :      &            ax*(bybarp*fin(2,i+1,j)+byp*fin(2,i+1,j+1))
    2554              : 
    2555              :             sum=sum+hx(v)*(
    2556              :      &         bxbar*(bybarp*fin(3,i,j)  +byp*fin(3,i,j+1))+
    2557            0 :      &            bx*(bybarp*fin(3,i+1,j)+byp*fin(3,i+1,j+1)))
    2558              : 
    2559            0 :             fval(v,iadr)=sum
    2560              :          end if
    2561              : 
    2562            0 :          if(ict(4) == 1) then
    2563              : 
    2564              : !  d2f/dxdy:
    2565              : 
    2566            0 :             iadr=iadr+1
    2567              : 
    2568              :             sum=hxi(v)*hyi(v)*(
    2569              :      &         axbarp*(aybarp*fin(0,i,j)  +ayp*fin(0,i,j+1))+
    2570            0 :      &            axp*(aybarp*fin(0,i+1,j)+ayp*fin(0,i+1,j+1)))
    2571              : 
    2572              :             sum=sum+hyi(v)*(
    2573              :      &         bxbarp*(aybarp*fin(1,i,j)  +ayp*fin(1,i,j+1))+
    2574            0 :      &            bxp*(aybarp*fin(1,i+1,j)+ayp*fin(1,i+1,j+1)))
    2575              : 
    2576              :             sum=sum+hxi(v)*(
    2577              :      &         axbarp*(bybarp*fin(2,i,j)  +byp*fin(2,i,j+1))+
    2578            0 :      &            axp*(bybarp*fin(2,i+1,j)+byp*fin(2,i+1,j+1)))
    2579              : 
    2580              :             sum=sum+
    2581              :      &         bxbarp*(bybarp*fin(3,i,j)  +byp*fin(3,i,j+1))+
    2582            0 :      &            bxp*(bybarp*fin(3,i+1,j)+byp*fin(3,i+1,j+1))
    2583              : 
    2584            0 :             fval(v,iadr)=sum
    2585              :          end if
    2586              : 
    2587              :       end do                             ! vector loop
    2588              : 
    2589            0 :       return
    2590            0 :       end subroutine herm2fcn_mesa_db
    2591              : 
    2592              : 
    2593     13745940 :       subroutine ibc_ck_db(ibc,slbl,xlbl,imin,imax,ier)
    2594              : 
    2595              : !  check that spline routine ibc flag is in range
    2596              : 
    2597              :       implicit none
    2598              :       integer ibc                       ! input -- flag value
    2599              :       character*(*) slbl                ! input -- subroutine name
    2600              :       character*(*) xlbl                ! input -- axis label
    2601              : 
    2602              :       integer imin                      ! input -- min allowed value
    2603              :       integer imax                      ! input -- max allowed value
    2604              : 
    2605              :       integer ier                       ! output -- set =1 if error detected
    2606              : 
    2607              : !----------------------
    2608              : 
    2609     13745940 :       if((ibc < imin).or.(ibc > imax)) then
    2610            0 :          ier=1
    2611              : !         write(6,1001) slbl,xlbl,ibc,imin,imax
    2612              : ! 1001    format(' ?',a,' -- ibc',a,' = ',i9,' out of range ',
    2613              : !     &      i2,' to ',i2)
    2614              :       end if
    2615              : 
    2616            0 :       return
    2617              :       end subroutine ibc_ck_db
    2618              : 
    2619              : 
    2620        33168 :       subroutine do_mkbicub_db(x,nx,y,ny,f1,nf2,
    2621        33168 :      &   ibcxmin,bcxmin,ibcxmax,bcxmax,
    2622        33168 :      &   ibcymin,bcymin,ibcymax,bcymax,
    2623              :      &   ilinx,iliny,ier)
    2624              : 
    2625              : !  setup bicubic spline, dynamic allocation of workspace
    2626              : !  fortran-90 fixed form source
    2627              : 
    2628              : !  --NOTE-- dmc 22 Feb 2004 -- rewrite for direct calculation of
    2629              : !  coefficients, to avoid large transient use of memory.
    2630              : 
    2631              : !
    2632              :       implicit NONE
    2633              : 
    2634              : !  input:
    2635              :       integer nx                        ! length of x vector
    2636              :       integer ny                        ! length of y vector
    2637              :       real(dp) x(:) ! (nx)                        ! x vector, strict ascending
    2638              :       real(dp) y(:) ! (ny)                        ! y vector, strict ascending
    2639              : 
    2640              :       integer nf2                       ! 2nd dimension of f, nf2 >= nx
    2641              : !  input/output:
    2642              :       real(dp), pointer :: f1(:) ! =(4,nf2,ny)                  ! data & spline coefficients
    2643              : 
    2644              : !  on input:  f(1,i,j) = f(x(i),y(j))
    2645              : !  on output:  f(1,i,j) unchanged
    2646              : !              f(2,i,j) = d2f/dx2(x(i),y(j))
    2647              : !              f(3,i,j) = d2f/dy2(x(i),y(j))
    2648              : !              f(4,i,j) = d4f/dx2dy2(x(i),y(j))
    2649              : 
    2650              : !  and the interpolation formula for (x,y) in (x(i),x(i+1))^(y(j),y(j+1))
    2651              : !  is:
    2652              : !        hx = x(i+1)-x(i)   hy = y(j+1)-y(j)
    2653              : !        dxp= (x-x(i))/hx   dxm= 1-dxp     dxp,dxm in (0,1)
    2654              : !        dyp= (x-x(i))/hx   dym= 1-dyp     dyp,dym in (0,1)
    2655              : !        dx3p = dxp**3-dxp  dx3m = dxm**3-dxm     dxp3,dxm3 in (0,1)
    2656              : 
    2657              : !   finterp = dxm*(dym*f(1,i,j)+dyp*f(1,i,j+1))
    2658              : !            +dxp*(dym*f(1,i+1,j)+dyp*f(1,i+1,j+1))
    2659              : !     +1/6*hx**2*
    2660              : !            dx3m*(dym*f(2,i,j)+dyp*f(2,i,j+1))
    2661              : !           +dx3p*(dym*f(2,i+1,j)+dyp*f(2,i+1,j+1))
    2662              : !     +1/6*hy**2*
    2663              : !            dxm*(dy3m*f(3,i,j)+dy3p*f(3,i,j+1))
    2664              : !           +dxp*(dy3m*f(3,i+1,j)+dy3p*f(3,i+1,j+1))
    2665              : !     +1/36*hx**2*hy**2*
    2666              : !            dx3m*(dym*f(4,i,j)+dyp*f(4,i,j+1))
    2667              : !           +dx3p*(dym*f(4,i+1,j)+dyp*f(4,i+1,j+1))
    2668              : 
    2669              : !  where the f(2:4,*,*) are cleverly evaluated to assure
    2670              : !  (a) finterp is continuous and twice differentiable across all
    2671              : !      grid cell boundaries, and
    2672              : !  (b) all boundary conditions are satisfied.
    2673              : 
    2674              : !  input bdy condition data:
    2675              :       integer ibcxmin                   ! bc flag for x=xmin
    2676              :       real(dp) bcxmin(:) ! (ny)                   ! bc data vs. y at x=xmin
    2677              :       integer ibcxmax                   ! bc flag for x=xmax
    2678              :       real(dp) bcxmax(:) ! (ny)                   ! bc data vs. y at x=xmax
    2679              : 
    2680              :       integer ibcymin                   ! bc flag for y=ymin
    2681              :       real(dp) bcymin(:) ! (nx)                   ! bc data vs. x at y=ymin
    2682              :       integer ibcymax                   ! bc flag for y=ymax
    2683              :       real(dp) bcymax(:) ! (nx)                   ! bc data vs. x at y=ymax
    2684              : 
    2685              : !  with interpretation:
    2686              : !   ibcxmin -- indicator for boundary condition at x(1):
    2687              : !    bcxmin(...) -- boundary condition data
    2688              : !     =-1 -- periodic boundary condition
    2689              : !     =0 -- use "not a knot"
    2690              : !     =1 -- match slope, specified at x(1),th(ith) by bcxmin(ith)
    2691              : !     =2 -- match 2nd derivative, specified at x(1),th(ith) by bcxmin(ith)
    2692              : !     =3 -- boundary condition is slope=0 (df/dx=0) at x(1), all th(j)
    2693              : !     =4 -- boundary condition is d2f/dx2=0 at x(1), all th(j)
    2694              : !     =5 -- match 1st derivative to 1st divided difference
    2695              : !     =6 -- match 2nd derivative to 2nd divided difference
    2696              : !     =7 -- match 3rd derivative to 3rd divided difference
    2697              : !           (for more detailed definition of BCs 5-7, see the
    2698              : !           comments of subroutine mkspline)
    2699              : !   NOTE bcxmin(...) referenced ONLY if ibcxmin=1 or ibcxmin=2
    2700              : 
    2701              : !   ibcxmax -- indicator for boundary condition at x(nx):
    2702              : !    bcxmax(...) -- boundary condition data
    2703              : !     (interpretation as with ibcxmin, bcxmin)
    2704              : !   NOTE:  if ibcxmin=-1, ibcxmax is ignored! ...and the BC is periodic.
    2705              : 
    2706              : !  and analogous interpretation for ibcymin,bcymin,ibcymax,bcymax
    2707              : !  (df/dy or d2f/dy2 boundary conditions at y=ymin and y=ymax).
    2708              : 
    2709              : !  output linear grid flags and completion code (ier=0 is normal):
    2710              : 
    2711              :       integer ilinx                     ! =1: x grid is "nearly" equally spaced
    2712              :       integer iliny                     ! =1: y grid is "nearly" equally spaced
    2713              : !  ilinx and iliny are set to zero if corresponding grids are not equally
    2714              : !  spaced
    2715              : 
    2716              :       integer ier                       ! =0 on exit if there is no error.
    2717              : 
    2718              : !  if there is an error, ier is set and a message is output on unit 6.
    2719              : !  these are considered programming errors in the calling routine.
    2720              : 
    2721              : !  possible errors:
    2722              : !    x(...) not strict ascending
    2723              : !    y(...) not strict ascending
    2724              : !    nx  <  4
    2725              : !    ny  <  4
    2726              : !    invalid boundary condition flag
    2727              : 
    2728              : !-----------------------
    2729              :       integer ierx,iery
    2730              : 
    2731        33168 :       real(dp), dimension(:,:), allocatable :: fwk
    2732        33168 :       real(dp) :: zbcmin,zbcmax
    2733              :       integer ix,iy,ibcmin,ibcmax
    2734              : 
    2735        33168 :       real(dp), dimension(:,:,:), allocatable :: fcorr
    2736              :       integer iflg2
    2737        99504 :       real(dp) zdiff(2),hy
    2738              : 
    2739        33168 :       real(dp), pointer :: f(:,:,:) ! =(4,nf2,ny)                  ! data & spline coefficients
    2740        33168 :       f(1:4,1:nf2,1:ny) => f1(1:4*nf2*ny)
    2741              : 
    2742              : 
    2743              : !-----------------------
    2744              : 
    2745              : !  see if 2nd pass is needed due to inhomogeneous d/dy bdy cond.
    2746              : 
    2747        33168 :       iflg2=0
    2748        33168 :       if(ibcymin /= -1) then
    2749        33168 :          if((ibcymin == 1).or.(ibcymin == 2)) then
    2750            0 :             do ix=1,nx
    2751            0 :                if (bcymin(ix) /= 0.d0) iflg2=1
    2752              :             end do
    2753              :          end if
    2754        33168 :          if((ibcymax == 1).or.(ibcymax == 2)) then
    2755            0 :             do ix=1,nx
    2756            0 :                if (bcymax(ix) /= 0.d0) iflg2=1
    2757              :             end do
    2758              :          end if
    2759              :       end if
    2760              : 
    2761              : !  check boundary condition specifications
    2762              : 
    2763        33168 :       ier=0
    2764              : 
    2765        33168 :       call ibc_ck_db(ibcxmin,'bcspline','xmin',-1,7,ier)
    2766        66336 :       if(ibcxmin >= 0) call ibc_ck_db(ibcxmax,'bcspline','xmax',0,7,ier)
    2767        33168 :       call ibc_ck_db(ibcymin,'bcspline','ymin',-1,7,ier)
    2768        33168 :       if(ibcymin >= 0) call ibc_ck_db(ibcymax,'bcspline','ymax',0,7,ier)
    2769              : 
    2770              : !  check ilinx & x vector
    2771              : 
    2772        33168 :       call splinck_db(x,nx,ilinx,1.0d-3,ierx)
    2773        33168 :       if(ierx /= 0) ier=2
    2774              : 
    2775              : !      if(ier == 2) then
    2776              : !         write(6,'('' ?bcspline:  x axis not strict ascending'')')
    2777              : !      end if
    2778              : 
    2779              : !  check iliny & y vector
    2780              : 
    2781        33168 :       call splinck_db(y,ny,iliny,1.0d-3,iery)
    2782        33168 :       if(iery /= 0) ier=3
    2783              : 
    2784              : !      if(ier == 3) then
    2785              : !         write(6,'('' ?bcspline:  y axis not strict ascending'')')
    2786              : !      end if
    2787              : 
    2788        33168 :       if(ier /= 0) return
    2789              : 
    2790              : !------------------------------------
    2791        33168 :       allocate(fwk(2,max(nx,ny)))
    2792              : 
    2793              : !  evaluate fxx (spline in x direction)
    2794              : 
    2795        33168 :       zbcmin=0
    2796        33168 :       zbcmax=0
    2797      2287242 :       do iy=1,ny
    2798    527688500 :          fwk(1,1:nx) = f(1,1:nx,iy)
    2799      2254074 :          if((ibcxmin == 1).or.(ibcxmin == 2)) zbcmin=bcxmin(iy)
    2800      2254074 :          if((ibcxmax == 1).or.(ibcxmax == 2)) zbcmax=bcxmax(iy)
    2801      2254074 :          call mkspline_db(x,nx,fwk,ibcxmin,zbcmin,ibcxmax,zbcmax,ilinx,ier)
    2802      2254074 :          if(ier /= 0) then
    2803            0 :             deallocate(fwk)
    2804            0 :             return
    2805              :          end if
    2806    527721668 :          f(2,1:nx,iy)=fwk(2,1:nx)
    2807              :       end do
    2808              : 
    2809              : !  evaluate fyy (spline in y direction)
    2810              : !  use homogeneous boundary condition; correction done later if necessary
    2811              : 
    2812        33168 :       zbcmin=0
    2813        33168 :       zbcmax=0
    2814        33168 :       ibcmin=ibcymin
    2815        33168 :       ibcmax=ibcymax
    2816      2309448 :       do ix=1,nx
    2817    527710706 :          fwk(1,1:ny) = f(1,ix,1:ny)
    2818      2276280 :          if(iflg2 == 1) then
    2819            0 :             if((ibcymin == 1).or.(ibcymin == 2)) ibcmin=0
    2820            0 :             if((ibcymax == 1).or.(ibcymax == 2)) ibcmax=0
    2821              :          end if
    2822      2276280 :          call mkspline_db(y,ny,fwk,ibcmin,zbcmin,ibcmax,zbcmax,iliny,ier)
    2823      2276280 :          if(ier /= 0) then
    2824            0 :             deallocate(fwk)
    2825            0 :             return
    2826              :          end if
    2827    527743874 :          f(3,ix,1:ny)=fwk(2,1:ny)
    2828              :       end do
    2829              : 
    2830              : !  evaluate fxxyy (spline fxx in y direction; BC simplified; avg
    2831              : !  d2(d2f/dx2)/dy2 and d2(df2/dy2)/dx2
    2832              : 
    2833              :       zbcmin=0
    2834              :       zbcmax=0
    2835        33168 :       ibcmin=ibcymin
    2836        33168 :       ibcmax=ibcymax
    2837      2309448 :       do ix=1,nx
    2838    527710706 :          fwk(1,1:ny) = f(2,ix,1:ny)
    2839      2276280 :          if(iflg2 == 1) then
    2840            0 :             if((ibcymin == 1).or.(ibcymin == 2)) ibcmin=0
    2841            0 :             if((ibcymax == 1).or.(ibcymax == 2)) ibcmax=0
    2842              :          end if
    2843              :          call mkspline_db(y,ny,fwk,
    2844      2276280 :      &      ibcmin,zbcmin,ibcmax,zbcmax,iliny,ier)
    2845      2276280 :          if(ier /= 0) then
    2846            0 :             deallocate(fwk)
    2847            0 :             return
    2848              :          end if
    2849    527743874 :          f(4,ix,1:ny)= fwk(2,1:ny)
    2850              :       end do
    2851              : 
    2852        33168 :       if(iflg2 == 1) then
    2853            0 :          allocate(fcorr(2,nx,ny))
    2854              : 
    2855              : !  correct for inhomogeneous y boundary condition
    2856              : 
    2857            0 :          do ix=1,nx
    2858              :             !  the desired inhomogeneouss BC is the difference btw the
    2859              :             !  requested derivative (1st or 2nd) and the current value
    2860              : 
    2861            0 :             zdiff(1)=0.d0
    2862            0 :             if(ibcymin == 1) then
    2863            0 :                hy=y(2)-y(1)
    2864              :                zdiff(1)=(f(1,ix,2)-f(1,ix,1))/hy +
    2865            0 :      &            hy*(-2*f(3,ix,1)-f(3,ix,2))/6
    2866            0 :                zdiff(1)=bcymin(ix)-zdiff(1)
    2867            0 :             else if(ibcymin == 2) then
    2868            0 :                zdiff(1)=bcymin(ix)-f(3,ix,1)
    2869              :             end if
    2870              : 
    2871            0 :             zdiff(2)=0.d0
    2872            0 :             if(ibcymax == 1) then
    2873            0 :                hy=y(ny)-y(ny-1)
    2874              :                zdiff(2)=(f(1,ix,ny)-f(1,ix,ny-1))/hy +
    2875            0 :      &            hy*(2*f(3,ix,ny)+f(3,ix,ny-1))/6
    2876            0 :                zdiff(2)=bcymax(ix)-zdiff(2)
    2877            0 :             else if(ibcymax == 2) then
    2878            0 :                zdiff(2)=bcymax(ix)-f(3,ix,ny)
    2879              :             end if
    2880              : 
    2881            0 :             fwk(1,1:ny)=0.d0  ! values are zero; only BC is not
    2882              :             call mkspline_db(y,ny,fwk,ibcymin,zdiff(1),ibcymax,zdiff(2),
    2883            0 :      &         iliny,ier)
    2884            0 :             if(ier /= 0) then
    2885            0 :                deallocate(fwk,fcorr)
    2886            0 :                return
    2887              :             end if
    2888            0 :             fcorr(1,ix,1:ny)=fwk(2,1:ny)  ! fyy-correction
    2889              :          end do
    2890              : 
    2891              :          zbcmin=0
    2892              :          zbcmax=0
    2893            0 :          do iy=1,ny
    2894            0 :             fwk(1,1:nx)=fcorr(1,1:nx,iy)
    2895            0 :             call mkspline_db(x,nx,fwk,ibcxmin,zbcmin,ibcxmax,zbcmax,ilinx,ier)
    2896            0 :             if(ier /= 0) then
    2897            0 :                deallocate(fwk,fcorr)
    2898            0 :                return
    2899              :             end if
    2900            0 :             fcorr(2,1:nx,iy)=fwk(2,1:nx)  ! fxxyy-correction
    2901              :          end do
    2902              : 
    2903            0 :          f(3:4,1:nx,1:ny)=f(3:4,1:nx,1:ny)+fcorr(1:2,1:nx,1:ny)
    2904              : 
    2905            0 :          deallocate(fcorr)
    2906              :       end if
    2907              : 
    2908              : !  correction spline -- f=fxx=zero; fyy & fxxyy are affected
    2909              : 
    2910        33168 :       deallocate(fwk)
    2911              : !------------------------------------
    2912              : 
    2913              : !  that's all
    2914              : 
    2915        33168 :       return
    2916        33168 :       end subroutine do_mkbicub_db
    2917              : 
    2918      6806634 :       subroutine mkspline_db(x,nx,fspl,ibcxmin,bcxmin,ibcxmax,bcxmax,
    2919              :      &   ilinx,ier)
    2920              :       implicit none
    2921              : 
    2922              : !  make a 2-coefficient 1d spline
    2923              : 
    2924              : !  only 2 coefficients, the data and its 2nd derivative, are needed to
    2925              : !  fully specify a spline.  See e.g. Numerical Recipes in Fortran-77
    2926              : !  (2nd edition) chapter 3, section on cubic splines.
    2927              : 
    2928              : !  input:
    2929              :       integer nx                        ! no. of data points
    2930              :       real(dp) x(nx)                        ! x axis data, strict ascending order
    2931              : 
    2932              : !  input/output:
    2933              :       real(dp) fspl(2,nx)                   ! f(1,*):  data in; f(2,*):  coeffs out
    2934              : 
    2935              : !     f(1,j) = f(x(j))  on input (unchanged on output)
    2936              : !     f(2,j) = f''(x(j)) (of interpolating spline) (on output).
    2937              : 
    2938              : !  ...boundary conditions...
    2939              : 
    2940              : !  input:
    2941              : 
    2942              :       integer ibcxmin                   ! b.c. flag @ x=xmin=x(1)
    2943              :       real(dp) bcxmin                       ! b.c. data @xmin
    2944              : 
    2945              :       integer ibcxmax                   ! b.c. flag @ x=xmax=x(nx)
    2946              :       real(dp) bcxmax                       ! b.c. data @xmax
    2947              : 
    2948              : !  ibcxmin=-1 -- periodic boundary condition
    2949              : !                (bcxmin,ibcxmax,bcxmax are ignored)
    2950              : 
    2951              : !                the output spline s satisfies
    2952              : !                s'(x(1))=s'(x(nx)) ..and.. s''(x(1))=s''(x(nx))
    2953              : 
    2954              : !  if non-periodic boundary conditions are used, then the xmin and xmax
    2955              : !  boundary conditions can be specified independently:
    2956              : 
    2957              : !  ibcxmin (ibcxmax) = 0 -- this specifies a "not a knot" boundary
    2958              : !                condition, see "cubsplb.for".  This is a common way
    2959              : !                for inferring a "good" spline boundary condition
    2960              : !                automatically from data in the vicinity of the
    2961              : !                boundary.  ... bcxmin (bcxmax) are ignored.
    2962              : 
    2963              : !  ibcxmin (ibcxmax) = 1 -- boundary condition is to have s'(x(1))
    2964              : !                ( s'(x(nx)) ) match the passed value bcxmin (bcxmax).
    2965              : 
    2966              : !  ibcxmin (ibcxmax) = 2 -- boundary condition is to have s''(x(1))
    2967              : !                ( s''(x(nx)) ) match the passed value bcxmin (bcxmax).
    2968              : 
    2969              : !  ibcxmin (ibcxmax) = 3 -- boundary condition is to have s'(x(1))=0.d0
    2970              : !                ( s'(x(nx))=0.d0 )
    2971              : 
    2972              : !  ibcxmin (ibcxmax) = 4 -- boundary condition is to have s''(x(1))=0.d0
    2973              : !                ( s''(x(nx))=0.d0 )
    2974              : 
    2975              : !  ibcxmin (ibcxmax) = 5 -- boundary condition is to have s'(x(1))
    2976              : !                ( s'(x(nx)) ) match the 1st divided difference
    2977              : !                e.g. at x(1):  d(1)/h(1), where
    2978              : !                           d(j)=f(1,j+1)-f(1,j)
    2979              : !                           h(j)=x(j+1)-x(j)
    2980              : 
    2981              : !  ibcxmin (ibcxmax) = 6 -- BC is to have s''(x(1)) ( s''(x(nx)) )
    2982              : !                match the 2nd divided difference
    2983              : !                e.g. at x(1):
    2984              : !                     e(1) = [d(2)/h(2) - d(1)/h(1)]/(0.5*(h(1)+h(2)))
    2985              : 
    2986              : !  ibcxmin (ibcxmax) = 7 -- BC is to have s'''(x(1)) ( s'''(x(nx)) )
    2987              : !                match the 3rd divided difference
    2988              : !                e.g. at x(1): [e(2)-e(1)]/(0.33333*(h(1)+h(2)+h(3)))
    2989              : 
    2990              : !  output:
    2991              : 
    2992              :       integer ilinx                     ! =1: hint, x axis is ~evenly spaced
    2993              : 
    2994              : !  let dx[avg] = (x(nx)-x(1))/(nx-1)
    2995              : !  let dx[j] = x(j+1)-x(j), for all j satisfying 1 <= j < nx
    2996              : 
    2997              : !  if for all such j, abs(dx[j]-dx[avg]) <= (1.0d-3*dx[avg]) then
    2998              : !  ilinx=1 is returned, indicating the data is (at least nearly)
    2999              : !  evenly spaced.  Even spacing is useful, for speed of zone lookup,
    3000              : !  when evaluating a spline.
    3001              : 
    3002              : !  if the even spacing condition is not satisfied, ilinx=2 is returned.
    3003              : 
    3004              :       integer ier                       ! exit code, 0=OK
    3005              : 
    3006              : !  an error code is returned if the x axis is not strict ascending,
    3007              : !  or if nx < 4, or if an invalid boundary condition specification was
    3008              : !  input.
    3009              : 
    3010              : !------------------------------------
    3011              : 
    3012              : !  this routine calls traditional 4 coefficient spline software, and
    3013              : !  translates the result to 2 coefficient form.
    3014              : 
    3015              : !  this could be done more efficiently but we decided out of conservatism
    3016              : !  to use the traditional software.
    3017              : 
    3018              : !------------------------------------
    3019              :       integer i, inwk
    3020              : !  workspaces -- f90 dynamically allocated
    3021              : 
    3022      6806634 :       real(dp), dimension(:,:), allocatable :: fspl4 ! traditional 4-spline
    3023      6806634 :       real(dp), dimension(:), allocatable :: wk ! cspline workspace
    3024              : 
    3025              : !------------------------------------
    3026              : 
    3027      6806634 :       allocate(fspl4(4,nx),wk(nx))
    3028              : 
    3029              : !  make the traditional call
    3030              : 
    3031   1583109912 :       do i=1,nx
    3032   1576303278 :          fspl4(1,i)=fspl(1,i)
    3033   1583109912 :          fspl(2,i)=0.d0                  ! for now
    3034              :       end do
    3035              : 
    3036      6806634 :       inwk=nx
    3037              : 
    3038              : !  boundary conditions imposed by cspline...
    3039              : 
    3040              :       call cspline_db(x,nx,fspl4,ibcxmin,bcxmin,ibcxmax,bcxmax,
    3041      6806634 :      &   wk,inwk,ilinx,ier)
    3042              : 
    3043      6806634 :       if(ier == 0) then
    3044              : 
    3045              : !  copy the output -- careful of end point.
    3046              : 
    3047   1576303278 :          do i=1,nx-1
    3048   1576303278 :             fspl(2,i) = 2.d0*fspl4(3,i)
    3049              :          end do
    3050      6806634 :          fspl(2,nx) = 2.d0*fspl4(3,nx-1) + (x(nx)-x(nx-1))*6.d0*fspl4(4,nx-1)
    3051              :       end if
    3052              : 
    3053      6806634 :       deallocate(fspl4,wk)
    3054              : 
    3055      6806634 :       return
    3056              :       end subroutine mkspline_db
    3057              : 
    3058              : 
    3059      6872970 :       subroutine splinck_db(x,inx,ilinx,ztol,ier)
    3060              :       implicit none
    3061              : 
    3062              : !  check if a grid is strictly ascending and if it is evenly spaced
    3063              : !  to w/in ztol
    3064              : 
    3065              :       integer inx
    3066              :       real(dp) x(inx)                       ! input -- grid to check
    3067              : 
    3068              :       integer ilinx                     ! output -- =1 if evenly spaced =2 O.W.
    3069              : 
    3070              :       real(dp) ztol                         ! input -- spacing check tolerance
    3071              : 
    3072              :       integer ier                       ! output -- =0 if OK
    3073              : 
    3074              : !  ier=1 is returned if x(1...inx) is NOT STRICTLY ASCENDING...
    3075              : 
    3076              : !-------------------------------
    3077              : 
    3078      6872970 :       real(dp) zeps, zdiffx, zdiff, dxavg
    3079              :       integer ix
    3080              : 
    3081      6872970 :       ier=0
    3082      6872970 :       ilinx=1
    3083      6872970 :       if(inx <= 1) return
    3084              : 
    3085      6872970 :       dxavg=(x(inx)-x(1))/(inx-1)
    3086      6872970 :       zeps=abs(ztol*dxavg)
    3087              : 
    3088   1580833632 :       do ix=2,inx
    3089   1573960662 :          zdiffx=(x(ix)-x(ix-1))
    3090   1573960662 :          if(zdiffx <= 0.0) ier=2
    3091   1573960662 :          zdiff=zdiffx-dxavg
    3092   1580833632 :          if(abs(zdiff) > zeps) then
    3093     48131078 :             ilinx=2
    3094              :          end if
    3095              :       end do
    3096              :  10   continue
    3097              : 
    3098              :       return
    3099              :       end subroutine splinck_db
    3100              : 
    3101      6806634 :       subroutine V_SPLINE_db(k_bc1,k_bcn,n,x,f,wk)
    3102              : !***********************************************************************
    3103              : !V_SPLINE evaluates the coefficients for a 1d cubic interpolating spline
    3104              : !References:
    3105              : !  Forsythe, Malcolm, Moler, Computer Methods for Mathematical
    3106              : !    Computations, Prentice-Hall, 1977, p.76
    3107              : !  Engeln-Muellges, Uhlig, Numerical Algorithms with Fortran, Springer,
    3108              : !    1996, p.251
    3109              : !  W.A.Houlberg, D.McCune 3/2000
    3110              : !Input:
    3111              : !  k_bc1-option for BC at x(1)
    3112              : !       =-1 periodic, ignore k_bcn
    3113              : !       =0 not-a-knot
    3114              : !       =1 s'(x1) = input value of f(2,1)
    3115              : !       =2 s''(x1) = input value of f(3,1)
    3116              : !       =3 s'(x1) = 0.0
    3117              : !       =4 s''(x1) = 0.0
    3118              : !       =5 match first derivative to first 2 points
    3119              : !       =6 match second derivative to first 3 points
    3120              : !       =7 match third derivative to first 4 points
    3121              : !       =else use not-a-knot
    3122              : !  k_bcn-option for boundary condition at x(n)
    3123              : !       =0 not-a-knot
    3124              : !       =1 s'(x1) = input value of f(2,1)
    3125              : !       =2 s''(x1) = input value of f(3,1)
    3126              : !       =3 s'(x1) = 0.0
    3127              : !       =4 s''(x1) = 0.0
    3128              : !       =5 match first derivative to first 2 points
    3129              : !       =6 match second derivative to first 3 points
    3130              : !       =7 match third derivative to first 4 points
    3131              : !       =else use knot-a-knot
    3132              : !  n-number of data points or knots-(n >= 2)
    3133              : !  x(n)-abscissas of the knots in strictly increasing order
    3134              : !  f(1,i)-ordinates of the knots
    3135              : !  f(2,1)-input value of s'(x1) for k_bc1=1
    3136              : !  f(2,n)-input value of s'(xn) for k_bcn=1
    3137              : !  f(3,1)-input value of s''(x1) for k_bc1=2
    3138              : !  f(3,n)-input value of s''(xn) for k_bcn=2
    3139              : !  wk(n)-scratch work area for periodic BC
    3140              : !Output:
    3141              : !  f(2,i)=s'(x(i))
    3142              : !  f(3,i)=s''(x(i))
    3143              : !  f(4,i)=s'''(x(i))
    3144              : !Comments:
    3145              : !  s(x)=f(1,i)+f(2,i)*(x-x(i))+f(3,i)*(x-x(i))**2/2!
    3146              : !       +f(4,i)*(x-x(i))**3/3! for x(i) <= x <= x(i+1)
    3147              : !  W_SPLINE can be used to evaluate the spline and its derivatives
    3148              : !  The cubic spline is twice differentiable (C2)
    3149              : 
    3150              : !  bugfixes -- dmc 24 Feb 2004:
    3151              : !    (a) fixed logic for not-a-knot:
    3152              : !          !    Set f(3,1) for not-a-knot
    3153              : !                    if (k_bc1 <= 0.or.k_bc1 > 7) then ...
    3154              : !        instead of
    3155              : !          !    Set f(3,1) for not-a-knot
    3156              : !                    if (k_bc1 <= 0.or.k_bc1 > 5) then ...
    3157              : !        and similarly for logic after cmt
    3158              : !          !    Set f(3,n) for not-a-knot
    3159              : !        as required since k_bc*=6 and k_bc*=7 are NOT not-a-knot BCs.
    3160              : 
    3161              : !    (b) the BCs to fix 2nd derivative at end points did not work if that
    3162              : !        2nd derivative were non-zero.  The reason is that in those cases
    3163              : !        the off-diagonal matrix elements nearest the corners are not
    3164              : !        symmetric; i.e. elem(1,2) /= elem(2,1) and
    3165              : !        elem(n-1,n) /= elem(n,n-1) where I use "elem" to refer to
    3166              : !        the tridiagonal matrix elements.  The correct values for the
    3167              : !        elements is:   elem(1,2)=0, elem(2,1)=x(2)-x(1)
    3168              : !                       elem(n,n-1)=0, elem(n-1,n)=x(n)-x(n-1)
    3169              : !        the old code in effect had these as all zeroes.  Since this
    3170              : !        meant the wrong set of linear equations was solved, the
    3171              : !        resulting spline had a discontinuity in its 1st derivative
    3172              : !        at x(2) and x(n-1).  Fixed by introducing elem21 and elemnn1
    3173              : !        to represent the non-symmetric lower-diagonal values.  Since
    3174              : !        elem21 & elemnn1 are both on the lower diagonals, logic to
    3175              : !        use them occurs in the non-periodic forward elimination loop
    3176              : !        only.  DMC 24 Feb 2004.
    3177              : !***********************************************************************
    3178              :       implicit none
    3179              : !Declaration of input variables
    3180              :       integer :: k_bc1, k_bcn, n
    3181              :       real(dp) :: x(*), wk(*), f(4,*)
    3182              : !Declaration in local variables
    3183              :       integer :: i, ib, imax, imin
    3184      6806634 :       real(dp) :: a1, an, b1, bn, q, t, hn
    3185      6806634 :       real(dp) :: elem21, elemnn1    ! (dmc)
    3186              : 
    3187              : !Set default range
    3188      6806634 :       imin=1
    3189      6806634 :       imax=n
    3190              : !Set first and second BC values
    3191      6806634 :       a1=0.d0
    3192      6806634 :       b1=0.d0
    3193      6806634 :       an=0.d0
    3194      6806634 :       bn=0.d0
    3195      6806634 :       if (k_bc1 == 1) then
    3196            0 :         a1=f(2,1)
    3197      6806634 :       else if(k_bc1 == 2) then
    3198            0 :         b1=f(3,1)
    3199      6806634 :       else if(k_bc1 == 5) then
    3200            0 :         a1=(f(1,2)-f(1,1))/(x(2)-x(1))
    3201      6806634 :       else if(k_bc1 == 6) then
    3202            0 :         b1=2.d0*((f(1,3)-f(1,2))/(x(3)-x(2)) -(f(1,2)-f(1,1))/(x(2)-x(1)))/(x(3)-x(1))
    3203              :       end if
    3204      6806634 :       if (k_bcn == 1) then
    3205            0 :         an=f(2,n)
    3206      6806634 :       else if(k_bcn == 2) then
    3207            0 :         bn=f(3,n)
    3208      6806634 :       else if(k_bcn == 5) then
    3209            0 :         an=(f(1,n)-f(1,n-1))/(x(n)-x(n-1))
    3210      6806634 :       else if(k_bcn == 6) then
    3211            0 :         bn=2.d0*((f(1,n)-f(1,n-1))/(x(n)-x(n-1)) -(f(1,n-1)-f(1,n-2))/(x(n-1)-x(n-2)))/(x(n)-x(n-2))
    3212              :       end if
    3213              : !Clear f(2:4,n)
    3214      6806634 :       f(2,n)=0.d0
    3215      6806634 :       f(3,n)=0.d0
    3216      6806634 :       f(4,n)=0.d0
    3217      6806634 :       if (n == 2) then
    3218              : !Coefficients for n=2
    3219            0 :         f(2,1)=(f(1,2)-f(1,1))/(x(2)-x(1))
    3220            0 :         f(3,1)=0.d0
    3221            0 :         f(4,1)=0.d0
    3222            0 :         f(2,2)=f(2,1)
    3223            0 :         f(3,2)=0.d0
    3224            0 :         f(4,2)=0.d0
    3225      6806634 :       else if(n > 2) then
    3226              : !Set up tridiagonal system for A*y=B where y(i) are the second
    3227              : !  derivatives at the knots
    3228              : !  f(2,i) are the diagonal elements of A
    3229              : !  f(4,i) are the off-diagonal elements of A
    3230              : !  f(3,i) are the B elements/3, and will become c/3 upon solution
    3231      6806634 :         f(4,1)=x(2)-x(1)
    3232      6806634 :         f(3,2)=(f(1,2)-f(1,1))/f(4,1)
    3233   1569496644 :         do i=2,n-1
    3234   1562690010 :           f(4,i)=x(i+1)-x(i)
    3235   1562690010 :           f(2,i)=2.d0*(f(4,i-1)+f(4,i))
    3236   1562690010 :           f(3,i+1)=(f(1,i+1)-f(1,i))/f(4,i)
    3237   1569496644 :           f(3,i)=f(3,i+1)-f(3,i)
    3238              :         end do
    3239              : 
    3240              : !  (dmc): save now:
    3241              : 
    3242      6806634 :         elem21=f(4,1)
    3243      6806634 :         elemnn1=f(4,n-1)
    3244              : 
    3245              : !  BC's
    3246              : !    Left
    3247              :         if (k_bc1 == -1) then
    3248            0 :           f(2,1)=2.d0*(f(4,1)+f(4,n-1))
    3249            0 :           f(3,1)=(f(1,2)-f(1,1))/f(4,1)-(f(1,n)-f(1,n-1))/f(4,n-1)
    3250            0 :           wk(1)=f(4,n-1)
    3251            0 :           do i=2,n-3
    3252            0 :             wk(i)=0.d0
    3253              :           end do
    3254            0 :           wk(n-2)=f(4,n-2)
    3255            0 :           wk(n-1)=f(4,n-1)
    3256              :         else if(k_bc1 == 1.or.k_bc1 == 3.or.k_bc1 == 5) then
    3257        12825 :           f(2,1)=2.d0*f(4,1)
    3258        12825 :           f(3,1)=(f(1,2)-f(1,1))/f(4,1)-a1
    3259              :         else if(k_bc1 == 2.or.k_bc1 == 4.or.k_bc1 == 6) then
    3260            0 :           f(2,1)=2.d0*f(4,1)
    3261            0 :           f(3,1)=f(4,1)*b1/3.d0
    3262            0 :           f(4,1)=0.d0  ! upper diagonal only (dmc: cf elem21)
    3263              :         else if(k_bc1 == 7) then
    3264            0 :           f(2,1)=-f(4,1)
    3265            0 :           f(3,1)=f(3,3)/(x(4)-x(2))-f(3,2)/(x(3)-x(1))
    3266            0 :           f(3,1)=f(3,1)*f(4,1)*f(4,1)/(x(4)-x(1))
    3267              :         else                             ! not a knot:
    3268      6793809 :           imin=2
    3269      6793809 :           f(2,2)=f(4,1)+2.d0*f(4,2)
    3270      6793809 :           f(3,2)=f(3,2)*f(4,2)/(f(4,1)+f(4,2))
    3271              :         end if
    3272              : !    Right
    3273      6806634 :         if (k_bcn == 1.or.k_bcn == 3.or.k_bcn == 5) then
    3274        12825 :           f(2,n)=2.d0*f(4,n-1)
    3275        12825 :           f(3,n)=-(f(1,n)-f(1,n-1))/f(4,n-1)+an
    3276              :         else if(k_bcn == 2.or.k_bcn == 4.or.k_bcn == 6) then
    3277            0 :           f(2,n)=2.d0*f(4,n-1)
    3278            0 :           f(3,n)=f(4,n-1)*bn/3.d0
    3279              : !xxx          f(4,n-1)=0.d0  ! dmc: preserve f(4,n-1) for back subst.
    3280            0 :           elemnn1=0.d0  !  lower diagonal only (dmc)
    3281              :         else if(k_bcn == 7) then
    3282            0 :           f(2,n)=-f(4,n-1)
    3283            0 :           f(3,n)=f(3,n-1)/(x(n)-x(n-2))-f(3,n-2)/(x(n-1)-x(n-3))
    3284            0 :           f(3,n)=-f(3,n)*f(4,n-1)*f(4,n-1)/(x(n)-x(n-3))
    3285      6793809 :         else if(k_bc1 /= -1) then         ! not a knot:
    3286      6793809 :           imax=n-1
    3287      6793809 :           f(2,n-1)=2.d0*f(4,n-2)+f(4,n-1)
    3288      6793809 :           f(3,n-1)=f(3,n-1)*f(4,n-2)/(f(4,n-1)+f(4,n-2))
    3289              :         end if
    3290              : !  Limit solution for only three points in domain
    3291      6806634 :         if (n == 3) then
    3292            0 :           f(3,1)=0.d0
    3293            0 :           f(3,n)=0.d0
    3294              :         end if
    3295      6806634 :         if (k_bc1 == -1) then
    3296              : !Solve system of equations for second derivatives at the knots
    3297              : !  Periodic BC
    3298              : !    Forward elimination
    3299            0 :           do i=2,n-2
    3300            0 :             t=f(4,i-1)/f(2,i-1)
    3301            0 :             f(2,i)=f(2,i)-t*f(4,i-1)
    3302            0 :             f(3,i)=f(3,i)-t*f(3,i-1)
    3303            0 :             wk(i)=wk(i)-t*wk(i-1)
    3304            0 :             q=wk(n-1)/f(2,i-1)
    3305            0 :             wk(n-1)=-q*f(4,i-1)
    3306            0 :             f(2,n-1)=f(2,n-1)-q*wk(i-1)
    3307            0 :             f(3,n-1)=f(3,n-1)-q*f(3,i-1)
    3308              :           end do
    3309              : !    Correct the n-1 element
    3310            0 :           wk(n-1)=wk(n-1)+f(4,n-2)
    3311              : !    Complete the forward elimination
    3312              : !    wk(n-1) and wk(n-2) are the off-diag elements of the lower corner
    3313            0 :           t=wk(n-1)/f(2,n-2)
    3314            0 :           f(2,n-1)=f(2,n-1)-t*wk(n-2)
    3315            0 :           f(3,n-1)=f(3,n-1)-t*f(3,n-2)
    3316              : !    Back substitution
    3317            0 :           f(3,n-1)=f(3,n-1)/f(2,n-1)
    3318            0 :           f(3,n-2)=(f(3,n-2)-wk(n-2)*f(3,n-1))/f(2,n-2)
    3319            0 :           do ib=3,n-1
    3320            0 :             i=n-ib
    3321            0 :             f(3,i)=(f(3,i)-f(4,i)*f(3,i+1)-wk(i)*f(3,n-1))/f(2,i)
    3322              :           end do
    3323            0 :           f(3,n)=f(3,1)
    3324              :         else
    3325              : !  Non-periodic BC
    3326              : !    Forward elimination
    3327              : !    For Not-A-Knot BC the off-diagonal end elements are not equal
    3328   1562715660 :           do i=imin+1,imax
    3329   1555909026 :             if ((i == n-1).and.(imax == n-1)) then
    3330      6793809 :               t=(f(4,i-1)-f(4,i))/f(2,i-1)
    3331              :             else
    3332   1549115217 :               if(i == 2) then
    3333        12825 :                  t=elem21/f(2,i-1)
    3334   1549102392 :               else if(i == n) then
    3335        12825 :                  t=elemnn1/f(2,i-1)
    3336              :               else
    3337   1549089567 :                  t=f(4,i-1)/f(2,i-1)
    3338              :               end if
    3339              :             end if
    3340   1555909026 :             if ((i == imin+1).and.(imin == 2)) then
    3341      6793809 :               f(2,i)=f(2,i)-t*(f(4,i-1)-f(4,i-2))
    3342              :             else
    3343   1549115217 :               f(2,i)=f(2,i)-t*f(4,i-1)
    3344              :             end if
    3345   1562715660 :             f(3,i)=f(3,i)-t*f(3,i-1)
    3346              :           end do
    3347              : !    Back substitution
    3348      6806634 :           f(3,imax)=f(3,imax)/f(2,imax)
    3349   1562715660 :           do ib=1,imax-imin
    3350   1555909026 :             i=imax-ib
    3351   1562715660 :             if ((i == 2).and.(imin == 2)) then
    3352      6793809 :               f(3,i)=(f(3,i)-(f(4,i)-f(4,i-1))*f(3,i+1))/f(2,i)
    3353              :             else
    3354   1549115217 :               f(3,i)=(f(3,i)-f(4,i)*f(3,i+1))/f(2,i)
    3355              :             end if
    3356              :           end do
    3357              : !    Reset d array to step size
    3358      6806634 :           f(4,1)=x(2)-x(1)
    3359      6806634 :           f(4,n-1)=x(n)-x(n-1)
    3360              : !    Set f(3,1) for not-a-knot
    3361      6806634 :           if (k_bc1 <= 0.or.k_bc1 > 7) then
    3362      6793809 :             f(3,1)=(f(3,2)*(f(4,1)+f(4,2))-f(3,3)*f(4,1))/f(4,2)
    3363              :           end if
    3364              : !    Set f(3,n) for not-a-knot
    3365      6806634 :           if (k_bcn <= 0.or.k_bcn > 7) then
    3366      6793809 :             f(3,n)=f(3,n-1)+(f(3,n-1)-f(3,n-2))*f(4,n-1)/f(4,n-2)
    3367              :           end if
    3368              :         end if
    3369              : !f(3,i) is now the sigma(i) of the text and f(4,i) is the step size
    3370              : !Compute polynomial coefficients
    3371   1576303278 :         do i=1,n-1
    3372   1569496644 :           f(2,i)= (f(1,i+1)-f(1,i))/f(4,i)-f(4,i)*(f(3,i+1)+2.d0*f(3,i))
    3373   1569496644 :           f(4,i)=(f(3,i+1)-f(3,i))/f(4,i)
    3374   1569496644 :           f(3,i)=6.d0*f(3,i)
    3375   1576303278 :           f(4,i)=6.d0*f(4,i)
    3376              :         end do
    3377      6806634 :         if (k_bc1 == -1) then
    3378            0 :           f(2,n)=f(2,1)
    3379            0 :           f(3,n)=f(3,1)
    3380            0 :           f(4,n)=f(4,1)
    3381              :         else
    3382      6806634 :            hn=x(n)-x(n-1)
    3383      6806634 :            f(2,n)=f(2,n-1)+hn*(f(3,n-1)+0.5d0*hn*f(4,n-1))
    3384      6806634 :            f(3,n)=f(3,n-1)+hn*f(4,n-1)
    3385      6806634 :            f(4,n)=f(4,n-1)
    3386              :            if (k_bcn == 1.or.k_bcn == 3.or.k_bcn == 5) then
    3387        12825 :               f(2,n)=an
    3388              :            else if(k_bcn == 2.or.k_bcn == 4.or.k_bcn == 6) then
    3389            0 :               f(3,n)=bn
    3390              :            end if
    3391              :         end if
    3392              :       end if
    3393      6806634 :       return
    3394              :       end subroutine V_SPLINE_db
    3395              : 
    3396              : 
    3397           24 :       subroutine zonfind_db(x,nx,zxget,i)
    3398              :       implicit none
    3399              : 
    3400              :       integer nx
    3401              :       real(dp) x(nx),zxget
    3402              :       integer i
    3403              : 
    3404              :       integer nxm, i1, i2, ii, ij
    3405           24 :       real(dp) dx
    3406              : 
    3407              : !  find index i such that x(i) <= zxget <= x(i+1)
    3408              : 
    3409              : !  x(1...nx) is strict increasing and x(1) <= zxget <= x(nx)
    3410              : !  (this is assumed to already have been checked -- no check here!)
    3411              : 
    3412           24 :       nxm=nx-1
    3413           24 :       if((i < 1).or.(i > nxm)) then
    3414              :          i1=1
    3415              :          i2=nx-1
    3416              :          GOTO 10
    3417              :       end if
    3418              : 
    3419            4 :       if(x(i) > zxget) then
    3420              : !  look down
    3421            2 :          dx=x(i+1)-x(i)
    3422            2 :          if((x(i)-zxget) > 4*dx) then
    3423            2 :             i1=1
    3424            2 :             i2=i-1
    3425            2 :             GOTO 10
    3426              :          else
    3427            0 :             i2=i-1
    3428            0 :             do ij=i2,1,-1
    3429            0 :                if((x(ij) <= zxget).and.(zxget <= x(ij+1))) then
    3430            0 :                   i=ij
    3431            0 :                   return
    3432              :                end if
    3433              :             end do
    3434            0 :             i=1
    3435            0 :             return
    3436              :          end if
    3437            2 :       else if(x(i+1) < zxget) then
    3438              : !  look up
    3439            2 :          dx=x(i+1)-x(i)
    3440            2 :          if((zxget-x(i+1)) > 4*dx) then
    3441              :             i1=i+1
    3442              :             i2=nxm
    3443              :             GOTO 10
    3444              :          else
    3445            0 :             i2=i+1
    3446            0 :             do ij=i2,nxm
    3447            0 :                if((x(ij) <= zxget).and.(zxget <= x(ij+1))) then
    3448            0 :                   i=ij
    3449            0 :                   return
    3450              :                end if
    3451              :             end do
    3452           24 :             ij=nxm
    3453              :             return
    3454              :          end if
    3455              :       else
    3456              : !  already there...
    3457              :          return
    3458              :       end if
    3459              : 
    3460              : !---------------------------
    3461              : !  binary search
    3462              : 
    3463              :  10   continue
    3464              : 
    3465          128 :       if(i1 == i2) then
    3466              : ! found by proc. of elimination
    3467           10 :          i=i1
    3468           10 :          return
    3469              :       end if
    3470              : 
    3471          118 :       ii=(i1+i2)/2
    3472              : 
    3473          118 :       if(zxget < x(ii)) then
    3474           56 :          i2=ii-1
    3475           62 :       else if(zxget > x(ii+1)) then
    3476              :          i1=ii+1
    3477              :       else
    3478              : ! found
    3479           14 :          i=ii
    3480           14 :          return
    3481              :       end if
    3482              : 
    3483              :       GOTO 10
    3484              : 
    3485              :       end subroutine zonfind_db
    3486              : 
    3487              :       end module bicub_db
        

Generated by: LCOV version 2.0-1