Integrate a function tabulated at arbitrarily spaced abscissas using overlapping parabolas.
DAVINT integrates a function tabulated at arbitrarily spaced abscissas. The limits of integration need not coincide with the tabulated abscissas.
A method of overlapping parabolas fitted to the data is used provided that there are at least 3 abscissas between the limits of integration. DAVINT also handles two special cases. If the limits of integration are equal, DAVINT returns a result of zero regardless of the number of tabulated values. If there are only two function values, DAVINT uses the trapezoid rule.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
real(kind=wp), | intent(in), | dimension(:) | :: | x |
array of abscissas, which must be in increasing order. |
|
real(kind=wp), | intent(in), | dimension(:) | :: | y |
array of function values. i.e., |
|
integer, | intent(in) | :: | n |
The integer number of function values supplied.
|
||
real(kind=wp), | intent(in) | :: | xlo |
lower limit of integration |
||
real(kind=wp), | intent(in) | :: | xup |
upper limit of integration. Must have |
||
real(kind=wp), | intent(out) | :: | ans |
computed approximate value of integral |
||
integer, | intent(out) | :: | ierr |
A status code:
ANS is set to zero if |
subroutine davint(x,y,n,xlo,xup,ans,ierr) implicit none real(wp),dimension(:),intent(in) :: x !! array of abscissas, which must be in increasing order. real(wp),dimension(:),intent(in) :: y !! array of function values. i.e., `y(i)=func(x(i))` integer,intent(in) :: n !! The integer number of function values supplied. !! `N >= 2` unless `XLO = XUP`. real(wp),intent(in) :: xlo !! lower limit of integration real(wp),intent(in) :: xup !! upper limit of integration. Must have `XLO <= XUP` real(wp),intent(out) :: ans !! computed approximate value of integral integer,intent(out) :: ierr !! A status code: !! !! * Normal Code !! * =1 Means the requested integration was performed. !! * Abnormal Codes !! * =2 Means `XUP` was less than `XLO`. !! * =3 Means the number of `X(I)` between `XLO` and `XUP` !! (inclusive) was less than 3 and neither of the two !! special cases described in the abstract occurred. !! No integration was performed. !! * =4 Means the restriction `X(I+1)>X(I)` was violated. !! * =5 Means the number `N` of function values was < 2. !! !! ANS is set to zero if `IERR` = 2, 3, 4, or 5. integer :: i , inlft , inrt , istart , istop real(wp) :: a , b , c , ca , cb , cc , fl , fr , r3 , & rp5 , slope , sum , syl , syl2 , syl3 , syu , & syu2 , syu3 , term1 , term2 , term3 , x1 , & x12 , x13 , x2 , x23 , x3 ierr = 1 ans = 0.0_wp ! error checks and trivial cases: if (xlo == xup) return if (xlo > xup) then ierr = 2 call xerror('the upper limit of integration was not greater '//& 'than the lower limit.',4,1) return end if if (n < 2) then ierr = 5 call xerror('less than two function values were supplied.', & 4,1) return end if do i = 2 , n if ( x(i)<=x(i-1) ) then ierr = 4 call xerror('the abscissas were not strictly increasing. must have '& //'x(i-1) < x(i) for all i.',4,1) return end if if ( x(i)>xup ) exit enddo if ( n<3 ) then ! special n=2 case slope = (y(2)-y(1))/(x(2)-x(1)) fl = y(1) + slope*(xlo-x(1)) fr = y(2) + slope*(xup-x(2)) ans = 0.5_wp*(fl+fr)*(xup-xlo) elseif ( x(n-2)<xlo ) then ierr = 3 call xerror('there were less than three function values '& //'between the limits of integration.',4,1) elseif ( x(3)<=xup ) then i = 1 do if ( x(i)>=xlo ) then inlft = i i = n do if ( x(i)<=xup ) then inrt = i if ( (inrt-inlft)>=2 ) then istart = inlft if ( inlft==1 ) istart = 2 istop = inrt if ( inrt==n ) istop = n - 1 r3 = 3.0_wp rp5 = 0.5_wp sum = 0.0_wp syl = xlo syl2 = syl*syl syl3 = syl2*syl do i = istart , istop x1 = x(i-1) x2 = x(i) x3 = x(i+1) x12 = x1 - x2 x13 = x1 - x3 x23 = x2 - x3 term1 = y(i-1)/(x12*x13) term2 = -y(i)/(x12*x23) term3 = y(i+1)/(x13*x23) a = term1 + term2 + term3 b = -(x2+x3)*term1 - (x1+x3)*term2 - (x1+x2)*term3 c = x2*x3*term1 + x1*x3*term2 + x1*x2*term3 if ( i>istart ) then ca = 0.5_wp*(a+ca) cb = 0.5_wp*(b+cb) cc = 0.5_wp*(c+cc) else ca = a cb = b cc = c endif syu = x2 syu2 = syu*syu syu3 = syu2*syu sum = sum + ca*(syu3-syl3)/r3 + cb*rp5*(syu2-syl2) + cc*(syu-syl) ca = a cb = b cc = c syl = syu syl2 = syu2 syl3 = syu3 enddo syu = xup ans = sum + ca*(syu**3-syl3)/r3 + cb*rp5*(syu**2-syl2) + cc*(syu-syl) else ierr = 3 call xerror('there were less than three function values '& //'between the limits of integration.',4,1) endif return endif i = i - 1 end do endif i = i + 1 end do else ierr = 3 call xerror('there were less than three function values '& //'between the limits of integration.',4,1) endif end subroutine davint