Compute Bessel functions Jv(z), Yv(z) and their
derivatives for a complex argument
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | v |
Order of |
||
| complex(kind=wp), | intent(in) | :: | z |
Complex argument |
||
| integer, | intent(out) | :: | Vm |
Highest order computed |
||
| complex(kind=wp), | intent(out), | dimension(0:*) | :: | Cbj |
|
|
| complex(kind=wp), | intent(out), | dimension(0:*) | :: | Cdj |
|
|
| complex(kind=wp), | intent(out), | dimension(0:*) | :: | Cby |
|
|
| complex(kind=wp), | intent(out), | dimension(0:*) | :: | Cdy |
|
subroutine cjyva(v,z,Vm,Cbj,Cdj,Cby,Cdy) real(wp),intent(in) :: v !! Order of `Jv(z)` and `Yv(z)` !! ( `v = n+v0`, `n = 0,1,2,...`, `0 ≤ v0 < 1 `) complex(wp),intent(in) :: z !! Complex argument integer,intent(out) :: Vm !! Highest order computed complex(wp),dimension(0:*),intent(out) :: Cbj !! `CBJ(n)` --- `Jn+v0(z)` complex(wp),dimension(0:*),intent(out) :: Cdj !! `CDJ(n)` --- `Jn+v0'(z)` complex(wp),dimension(0:*),intent(out) :: Cby !! `CBY(n)` --- `Yn+v0(z)` complex(wp),dimension(0:*),intent(out) :: Cdy !! `CDY(n)` --- `Yn+v0'(z)` real(wp) :: a0 , ga , gb , pv0 , pv1 , v0 , vg , vl , & vv , w0 , w1 , wa , ya0 , ya1 , yak complex(wp) :: ca , ca0 , cb , cck , cec , & cf , cf0 , cf1 , cf2 , cfac0 , cfac1 , cg0 , cg1 , & ch0 , ch1 , ch2 , ci , cju0 , cju1 , cjv0 , cjv1 , & cjvl , cp11 , cp12 , cp21 , cp22 , cpz , cqz , cr , & cr0 , cr1 , crp , crq , cs , cs0 , cs1 , csk , cyk , & cyl1 , cyl2 , cylk , cyv0 , cyv1 , z1 , z2 , zk integer :: j , k , k0 , l , lb , lb0 , m , n real(wp),parameter :: rp2 = 2.0_wp / pi ! 0.63661977236758d0 ci = (0.0_wp,1.0_wp) a0 = abs(z) z1 = z z2 = z*z n = int(v) v0 = v - n pv0 = pi*v0 pv1 = pi*(1.0_wp+v0) if ( a0<1.0e-100_wp ) then do k = 0 , n Cbj(k) = (0.0_wp,0.0_wp) Cdj(k) = (0.0_wp,0.0_wp) Cby(k) = -(1.0e+300_wp,0.0_wp) Cdy(k) = (1.0e+300_wp,0.0_wp) enddo if ( v0==0.0_wp ) then Cbj(0) = (1.0_wp,0.0_wp) Cdj(1) = (0.5_wp,0.0_wp) else Cdj(0) = (1.0e+300_wp,0.0_wp) endif Vm = v return endif lb0 = 0.0_wp if ( real(z,wp)<0.0_wp ) z1 = -z if ( a0<=12.0_wp ) then do l = 0 , 1 vl = v0 + l cjvl = (1.0_wp,0.0_wp) cr = (1.0_wp,0.0_wp) do k = 1 , 40 cr = -0.25_wp*cr*z2/(k*(k+vl)) cjvl = cjvl + cr if ( abs(cr)<abs(cjvl)*1.0e-15_wp ) exit enddo vg = 1.0_wp + vl call gamma2(vg,ga) ca = (0.5_wp*z1)**vl/ga if ( l==0 ) cjv0 = cjvl*ca if ( l==1 ) cjv1 = cjvl*ca enddo else k0 = 11 if ( a0>=35.0_wp ) k0 = 10 if ( a0>=50.0_wp ) k0 = 8 do j = 0 , 1 vv = 4.0_wp*(j+v0)*(j+v0) cpz = (1.0_wp,0.0_wp) crp = (1.0_wp,0.0_wp) do k = 1 , k0 crp = -0.78125e-2_wp*crp*(vv-(4.0_wp*k-3.0_wp)**2.0_wp) & *(vv-(4.0_wp*k-1.0_wp)**2.0_wp)/(k*(2.0_wp*k-1.0_wp)*z2) cpz = cpz + crp enddo cqz = (1.0_wp,0.0_wp) crq = (1.0_wp,0.0_wp) do k = 1 , k0 crq = -0.78125e-2_wp*crq*(vv-(4.0_wp*k-1.0_wp)**2.0_wp) & & *(vv-(4.0_wp*k+1.0_wp)**2.0_wp)/(k*(2.0_wp*k+1.0_wp)*z2) cqz = cqz + crq enddo cqz = 0.125_wp*(vv-1.0_wp)*cqz/z1 zk = z1 - (0.5_wp*(j+v0)+0.25_wp)*pi ca0 = sqrt(rp2/z1) cck = cos(zk) csk = sin(zk) if ( j==0 ) then cjv0 = ca0*(cpz*cck-cqz*csk) cyv0 = ca0*(cpz*csk+cqz*cck) elseif ( j==1 ) then cjv1 = ca0*(cpz*cck-cqz*csk) cyv1 = ca0*(cpz*csk+cqz*cck) endif enddo endif if ( a0<=12.0_wp ) then if ( v0/=0.0_wp ) then do l = 0 , 1 vl = v0 + l cjvl = (1.0_wp,0.0_wp) cr = (1.0_wp,0.0_wp) do k = 1 , 40 cr = -0.25_wp*cr*z2/(k*(k-vl)) cjvl = cjvl + cr if ( abs(cr)<abs(cjvl)*1.0e-15_wp ) exit enddo vg = 1.0_wp - vl call gamma2(vg,gb) cb = (2.0_wp/z1)**vl/gb if ( l==0 ) cju0 = cjvl*cb if ( l==1 ) cju1 = cjvl*cb enddo cyv0 = (cjv0*cos(pv0)-cju0)/sin(pv0) cyv1 = (cjv1*cos(pv1)-cju1)/sin(pv1) else cec = log(z1/2.0_wp) + gamma ! 0.5772156649015329 cs0 = (0.0_wp,0.0_wp) w0 = 0.0_wp cr0 = (1.0_wp,0.0_wp) do k = 1 , 30 w0 = w0 + 1.0_wp/k cr0 = -0.25_wp*cr0/(k*k)*z2 cs0 = cs0 + cr0*w0 enddo cyv0 = rp2*(cec*cjv0-cs0) cs1 = (1.0_wp,0.0_wp) w1 = 0.0_wp cr1 = (1.0_wp,0.0_wp) do k = 1 , 30 w1 = w1 + 1.0_wp/k cr1 = -0.25_wp*cr1/(k*(k+1))*z2 cs1 = cs1 + cr1*(2.0_wp*w1+1.0_wp/(k+1.0_wp)) enddo cyv1 = rp2*(cec*cjv1-1.0_wp/z1-0.25_wp*z1*cs1) endif endif if ( real(z,wp)<0.0_wp ) then cfac0 = exp(pv0*ci) cfac1 = exp(pv1*ci) if ( aimag(z)<0.0_wp ) then cyv0 = cfac0*cyv0 - 2.0_wp*ci*cos(pv0)*cjv0 cyv1 = cfac1*cyv1 - 2.0_wp*ci*cos(pv1)*cjv1 cjv0 = cjv0/cfac0 cjv1 = cjv1/cfac1 elseif ( aimag(z)>0.0_wp ) then cyv0 = cyv0/cfac0 + 2.0_wp*ci*cos(pv0)*cjv0 cyv1 = cyv1/cfac1 + 2.0_wp*ci*cos(pv1)*cjv1 cjv0 = cfac0*cjv0 cjv1 = cfac1*cjv1 endif endif Cbj(0) = cjv0 Cbj(1) = cjv1 if ( n>=2 .and. n<=int(0.25_wp*a0) ) then cf0 = cjv0 cf1 = cjv1 do k = 2 , n cf = 2.0_wp*(k+v0-1.0_wp)/z*cf1 - cf0 Cbj(k) = cf cf0 = cf1 cf1 = cf enddo elseif ( n>=2 ) then m = msta1(a0,200) if ( m<n ) then n = m else m = msta2(a0,n,15) endif cf2 = (0.0_wp,0.0_wp) cf1 = (1.0e-100_wp,0.0_wp) do k = m , 0 , -1 cf = 2.0_wp*(v0+k+1.0_wp)/z*cf1 - cf2 if ( k<=n ) Cbj(k) = cf cf2 = cf1 cf1 = cf enddo if ( abs(cjv0)>abs(cjv1) ) cs = cjv0/cf if ( abs(cjv0)<=abs(cjv1) ) cs = cjv1/cf2 do k = 0 , n Cbj(k) = cs*Cbj(k) enddo endif Cdj(0) = v0/z*Cbj(0) - Cbj(1) do k = 1 , n Cdj(k) = -(k+v0)/z*Cbj(k) + Cbj(k-1) enddo Cby(0) = cyv0 Cby(1) = cyv1 ya0 = abs(cyv0) lb = 0 cg0 = cyv0 cg1 = cyv1 do k = 2 , n cyk = 2.0_wp*(v0+k-1.0_wp)/z*cg1 - cg0 if ( abs(cyk)<=1.0e+290_wp ) then yak = abs(cyk) ya1 = abs(cg0) if ( yak<ya0 .and. yak<ya1 ) lb = k Cby(k) = cyk cg0 = cg1 cg1 = cyk endif enddo if ( lb>4 .and. aimag(z)/=0.0_wp ) then do if ( lb/=lb0 ) then ch2 = (1.0_wp,0.0_wp) ch1 = (0.0_wp,0.0_wp) lb0 = lb do k = lb , 1 , -1 ch0 = 2.0_wp*(k+v0)/z*ch1 - ch2 ch2 = ch1 ch1 = ch0 enddo cp12 = ch0 cp22 = ch2 ch2 = (0.0_wp,0.0_wp) ch1 = (1.0_wp,0.0_wp) do k = lb , 1 , -1 ch0 = 2.0_wp*(k+v0)/z*ch1 - ch2 ch2 = ch1 ch1 = ch0 enddo cp11 = ch0 cp21 = ch2 if ( lb==n ) Cbj(lb+1) = 2.0_wp*(lb+v0)/z*Cbj(lb) - Cbj(lb-1) if ( abs(Cbj(0))>abs(Cbj(1)) ) then Cby(lb+1) = (Cbj(lb+1)*cyv0-2.0_wp*cp11/(pi*z))/Cbj(0) Cby(lb) = (Cbj(lb)*cyv0+2.0_wp*cp12/(pi*z))/Cbj(0) else Cby(lb+1) = (Cbj(lb+1)*cyv1-2.0_wp*cp21/(pi*z))/Cbj(1) Cby(lb) = (Cbj(lb)*cyv1+2.0_wp*cp22/(pi*z))/Cbj(1) endif cyl2 = Cby(lb+1) cyl1 = Cby(lb) do k = lb - 1 , 0 , -1 cylk = 2.0_wp*(k+v0+1.0_wp)/z*cyl1 - cyl2 Cby(k) = cylk cyl2 = cyl1 cyl1 = cylk enddo cyl1 = Cby(lb) cyl2 = Cby(lb+1) do k = lb + 1 , n - 1 cylk = 2.0_wp*(k+v0)/z*cyl2 - cyl1 Cby(k+1) = cylk cyl1 = cyl2 cyl2 = cylk enddo do k = 2 , n wa = abs(Cby(k)) if ( wa<abs(Cby(k-1)) ) lb = k enddo else exit endif end do endif Cdy(0) = v0/z*Cby(0) - Cby(1) do k = 1 , n Cdy(k) = Cby(k-1) - (k+v0)/z*Cby(k) enddo Vm = n + v0 end subroutine cjyva