Compute an approximation for the incomplete or complete elliptic integral of the 2nd kind: Where , , , and .
If or , the integral is complete.
The duplication theorem is iterated until the variables are nearly equal, and the function is then expanded in Taylor series to fifth order.
Legendre form of ELLIPTIC INTEGRAL of 2nd kind:
When the integral is complete:
Bulirsch form of ELLIPTIC INTEGRAL of 2nd kind:
Legendre form of alternative ELLIPTIC INTEGRAL of 2nd kind:
Lemniscate constant B:
Heuman's LAMBDA function:
Jacobi ZETA function:
Changes in the program may improve speed at the expense of robustness.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | x | nonnegative variable () |
||
| real(kind=wp), | intent(in) | :: | y | nonnegative variable () |
||
| real(kind=wp), | intent(in) | :: | z | positive variable |
||
| integer, | intent(out) | :: | ier | indicates normal or abnormal termination:
|
real(wp) function drd(x,y,z,ier)
implicit none
real(wp),intent(in) :: x !! nonnegative variable (\(x+y>0\))
real(wp),intent(in) :: y !! nonnegative variable (\(x+y>0\))
real(wp),intent(in) :: z !! positive variable
integer,intent(out) :: ier !! indicates normal or abnormal termination:
!!
!! * `IER = 0`: Normal and reliable termination of the
!! routine. It is assumed that the requested
!! accuracy has been achieved.
!! * `IER > 0`: Abnormal termination of the routine:
!! * `IER = 1`: `min(x,y) < 0`
!! * `IER = 2`: `min(x + y, z ) < LOLIM`
!! * `IER = 3`: `max(x,y,z) > UPLIM`
character(len=16) :: xern3 , xern4 , xern5 , xern6
real(wp) :: epslon, ea , eb , ec , ed , ef , lamda
real(wp) :: mu , power4 , sigma , s1 , s2 , xn , xndev
real(wp) :: xnroot , yn , yndev , ynroot , zn , zndev , znroot
real(wp),parameter :: errtol = (d1mach(3)/3.0_wp)**(1.0_wp/6.0_wp)
!! Determines the accuracy of the answer.
!! The value assigned by the routine will result
!! in solution precision within 1-2 decimals of
!! machine precision.
!!
!! Relative error due to truncation is less than
!! `3 * ERRTOL ** 6 / (1-ERRTOL) ** 3/2`.
!!
!! The accuracy of the computed approximation to the integral
!! can be controlled by choosing the value of ERRTOL.
!! Truncation of a Taylor series after terms of fifth order
!! introduces an error less than the amount shown in the
!! second column of the following table for each value of
!! ERRTOL in the first column. In addition to the truncation
!! error there will be round-off error, but in practice the
!! total error from both sources is usually less than the
!! amount given in the table.
!!
!! Sample choices:
!! (ERRTOL, Relative truncation error less than):
!! (1.0e-3, 4.0e-18),
!! (3.0e-3, 3.0e-15),
!! (1.0e-2, 4.0e-12),
!! (3.0e-2, 3.0e-9),
!! (1.0e-1, 4.0e-6)
!!
!! Decreasing ERRTOL by a factor of 10 yields six more
!! decimal digits of accuracy at the expense of one or
!! two more iterations of the duplication theorem.
real(wp),parameter :: lolim = 2.0_wp/(d1mach(2))**(2.0_wp/3.0_wp) !! Lower limit of valid arguments
real(wp),parameter :: tuplim = (0.10_wp*errtol)**(1.0_wp/3.0_wp)/&
d1mach(1)**(1.0_wp/3.0_wp)
real(wp),parameter :: uplim = tuplim**2 !! Upper limit of valid arguments
real(wp),parameter :: c1 = 3.0_wp/14.0_wp
real(wp),parameter :: c2 = 1.0_wp/6.0_wp
real(wp),parameter :: c3 = 9.0_wp/22.0_wp
real(wp),parameter :: c4 = 3.0_wp/26.0_wp
! initialize:
drd = 0.0_wp
! check for errors:
if ( min(x,y)<0.0_wp ) then
ier = 1
write (xern3,'(1pe15.6)') x
write (xern4,'(1pe15.6)') y
write(error_unit,'(a)') 'drd: min(x,y)<0 where x = '//xern3// &
' and y = '//xern4
return
endif
if ( max(x,y,z)>uplim ) then
ier = 3
write (xern3,'(1pe15.6)') x
write (xern4,'(1pe15.6)') y
write (xern5,'(1pe15.6)') z
write (xern6,'(1pe15.6)') uplim
write(error_unit,'(a)') 'drd: max(x,y,z)>uplim where x = '// &
xern3//' y = '//xern4//' z = '//xern5// &
' and uplim = '//xern6
return
endif
if ( min(x+y,z)<lolim ) then
ier = 2
write (xern3,'(1pe15.6)') x
write (xern4,'(1pe15.6)') y
write (xern5,'(1pe15.6)') z
write (xern6,'(1pe15.6)') lolim
write(error_unit,'(a)') 'drd: min(x+y,z)<lolim where x = '// &
xern3//' y = '//xern4//' z = '//xern5// &
' and lolim = '//xern6
return
endif
ier = 0
xn = x
yn = y
zn = z
sigma = 0.0_wp
power4 = 1.0_wp
do
mu = (xn+yn+3.0_wp*zn)*0.20_wp
xndev = (mu-xn)/mu
yndev = (mu-yn)/mu
zndev = (mu-zn)/mu
epslon = max(abs(xndev),abs(yndev),abs(zndev))
if ( epslon<errtol ) exit
xnroot = sqrt(xn)
ynroot = sqrt(yn)
znroot = sqrt(zn)
lamda = xnroot*(ynroot+znroot) + ynroot*znroot
sigma = sigma + power4/(znroot*(zn+lamda))
power4 = power4*0.250_wp
xn = (xn+lamda)*0.250_wp
yn = (yn+lamda)*0.250_wp
zn = (zn+lamda)*0.250_wp
end do
ea = xndev*yndev
eb = zndev*zndev
ec = ea - eb
ed = ea - 6.0_wp*eb
ef = ed + ec + ec
s1 = ed*(-c1+0.250_wp*c3*ed-1.50_wp*c4*zndev*ef)
s2 = zndev*(c2*ef+zndev*(-c3*ec+zndev*c4*ea))
drd = 3.0_wp*sigma + power4*(1.0_wp+s1+s2)/(mu*sqrt(mu))
end function drd