Piecewise Cubic Hermite Integrator, Arbitrary limits
Evaluates the definite integral of the cubic Hermite function defined by N, X, F, D over the interval [A, B].
To provide compatibility with dpchim and dpchic, includes an increment between successive values of the F- and D-arrays.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
integer, | intent(in) | :: | n |
number of data points. (Error return if N<2). |
||
real(kind=wp), | intent(in) | :: | x(*) |
array of independent variable values. The
elements of X must be strictly increasing:
|
||
real(kind=wp), | intent(in) | :: | f(incfd,*) |
array of function values. F(1+(I-1)*INCFD) is the value corresponding to X(I). |
||
real(kind=wp), | intent(in) | :: | d(incfd,*) |
array of derivative values. D(1+(I-1)*INCFD) is the value corresponding to X(I). |
||
integer, | intent(in) | :: | incfd |
increment between successive values in F and D. (Error return if INCFD<1). |
||
logical, | intent(inout) | :: | skip |
logical variable which should be set to .TRUE. if the user wishes to skip checks for validity of preceding parameters, or to .FALSE. otherwise. This will save time in case these checks have already been performed (say, in dpchim or dpchic). SKIP will be set to .TRUE. on return with IERR>=0 . |
||
real(kind=wp), | intent(in) | :: | a |
the limits of integration. NOTE: There is no requirement that [A,B] be contained in [X(1),X(N)]. However, the resulting integral value will be highly suspect, if not. |
||
real(kind=wp), | intent(in) | :: | b |
the limits of integration. NOTE: There is no requirement that [A,B] be contained in [X(1),X(N)]. However, the resulting integral value will be highly suspect, if not. |
||
integer, | intent(inout) | :: | ierr |
error flag.
|
value of the requested integral.
function dpchia (n, x, f, d, incfd, skip, a, b, ierr) result(value) integer,intent(in) :: n !! number of data points. (Error return if N<2). integer,intent(in) :: incfd !! increment between successive values in F and D. !! (Error return if INCFD<1). integer,intent(inout) :: ierr !! error flag. !! !! * Normal return: !! * IERR = 0 (no errors). !! * Warning errors: !! * IERR = 1 if A is outside the interval [X(1),X(N)]. !! * IERR = 2 if B is outside the interval [X(1),X(N)]. !! * IERR = 3 if both of the above are true. (Note that this !! means that either [A,B] contains data interval !! or the intervals do not intersect at all.) !! * "Recoverable" errors: !! * IERR = -1 if N<2 . !! * IERR = -2 if INCFD<1 . !! * IERR = -3 if the X-array is not strictly increasing. !! (VALUE will be zero in any of these cases.) !! NOTE: The above errors are checked in the order listed, !! and following arguments have **NOT** been validated. !! * IERR = -4 in case of an error return from DPCHID (which !! should never occur). real(wp),intent(in) :: x(*) !! array of independent variable values. The !! elements of X must be strictly increasing: !! `X(I-1) < X(I), I = 2(1)N`. !! (Error return if not.) real(wp),intent(in) :: f(incfd,*) !! array of function values. F(1+(I-1)*INCFD) is !! the value corresponding to X(I). real(wp),intent(in) :: d(incfd,*) !! array of derivative values. D(1+(I-1)*INCFD) !! is the value corresponding to X(I). real(wp),intent(in) :: a !! the limits of integration. !! NOTE: There is no requirement that [A,B] be contained in !! [X(1),X(N)]. However, the resulting integral value !! will be highly suspect, if not. real(wp),intent(in) :: b !! the limits of integration. !! NOTE: There is no requirement that [A,B] be contained in !! [X(1),X(N)]. However, the resulting integral value !! will be highly suspect, if not. logical,intent(inout) :: skip !! logical variable which should be set to !! .TRUE. if the user wishes to skip checks for validity of !! preceding parameters, or to .FALSE. otherwise. !! This will save time in case these checks have already !! been performed (say, in [[dpchim]] or [[dpchic]]). !! SKIP will be set to .TRUE. on return with IERR>=0 . real(wp) :: value !! value of the requested integral. integer :: i, ia, ib, ierd, il, ir real(wp) :: xa, xb value = zero ! validity-check arguments. if (.not. skip) then if ( n<2 ) then ierr = -1 call xermsg ('PCHIP', 'dpchia', 'number of data points less than two', ierr, 1) return end if if ( incfd<1 ) then ierr = -2 call xermsg ('PCHIP', 'dpchia', 'increment less than one', ierr, 1) return end if do i = 2, n if ( x(i)<=x(i-1) ) then ierr = -3 call xermsg ('PCHIP', 'dpchia', 'x-array not strictly increasing', ierr, 1) return end if end do end if ! function definition is ok, go on. skip = .true. ierr = 0 if ( (a<x(1)) .or. (a>x(n)) ) ierr = ierr + 1 if ( (b<x(1)) .or. (b>x(n)) ) ierr = ierr + 2 ! compute integral value. if (a /= b) then xa = min (a, b) xb = max (a, b) if (xb <= x(2)) then ! interval is to left of x(2), so use first cubic. value = dchfie (x(1),x(2), f(1,1),f(1,2), & d(1,1),d(1,2), a, b) else if (xa >= x(n-1)) then ! interval is to right of x(n-1), so use last cubic. value = dchfie(x(n-1),x(n), f(1,n-1),f(1,n), & d(1,n-1),d(1,n), a, b) else ! 'normal' case -- xa<xb, xa<x(n-1), xb>x(2). ! locate ia and ib such that ! x(ia-1)<xa<=x(ia)<=x(ib)<=xb<=x(ib+1) ia = 1 do i = 1, n-1 if (xa > x(i)) ia = i + 1 end do ! ia = 1 implies xa<x(1) . otherwise, ! ia is largest index such that x(ia-1)<xa,. ib = n do i = n, ia, -1 if (xb < x(i)) ib = i - 1 end do ! ib = n implies xb>x(n) . otherwise, ! ib is smallest index such that xb<x(ib+1) . ! compute the integral. if (ib < ia) then ! this means ib = ia-1 and ! (a,b) is a subset of (x(ib),x(ia)). value = dchfie (x(ib),x(ia), f(1,ib),f(1,ia), & d(1,ib),d(1,ia), a, b) else ! first compute integral over (x(ia),x(ib)). ! (case (ib == ia) is taken care of by initialization ! of value to zero.) if (ib > ia) then value = dpchid (n, x, f, d, incfd, skip, ia, ib, ierd) if (ierd < 0) then ! trouble in dpchid. (should never occur.) ierr = -4 call xermsg ('PCHIP', 'dpchia', 'trouble in dpchid', ierr, 1) return end if endif ! then add on integral over (xa,x(ia)). if (xa < x(ia)) then il = max(1, ia-1) ir = il + 1 value = value + dchfie (x(il),x(ir), f(1,il),f(1,ir), & d(1,il),d(1,ir), xa, x(ia)) endif ! then add on integral over (x(ib),xb). if (xb > x(ib)) then ir = min (ib+1, n) il = ir - 1 value = value + dchfie (x(il),x(ir), f(1,il),f(1,ir), & d(1,il),d(1,ir), x(ib), xb) endif ! finally, adjust sign if necessary. if (a > b) value = -value endif endif endif end function dpchia