bessel.tcl
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 namespace ::math::special {
00015
00016
00017
00018 ::math::constants::constants pi
00019
00020
00021
00022
00023 namespace export J0 J1 Jn J1/2 J-1/2 I_n
00024 }
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 ret ::math::special::J0 (type x) {
00035 Jn 0 $x
00036 }
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 ret ::math::special::J1 (type x) {
00047 Jn 1 $x
00048 }
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 ret ::math::special::Jn (type n , type x) {
00069 variable pi
00070
00071 if { ![string is integer -strict $n] } {
00072 return -code error "Order argument must be integer"
00073 }
00074
00075 #
00076 # Integrate over the interval [0,pi] using a small
00077 # enough step - 40 points should do a good job
00078 # with |x| < 20, n < 20 (an accuracy of 1.0e-8
00079 # is reported by Davis and Rabinowitz)
00080 #
00081 set number 40
00082 set step [expr {$pi/double($number)}]
00083 set result 0.0
00084
00085 for { set i 0 } { $i <= $number } { incr i } {
00086 set t [expr {double($i)*$step}]
00087 set f [expr {cos($x * sin($t) - $n * $t)}]
00088 if { $i == 0 || $i == $number } {
00089 set f [expr {$f/2.0}]
00090 }
00091 set result [expr {$result+$f}]
00092 }
00093
00094 expr {$result*$step/$pi}
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 ret ::math::special::J1/2 (type x) {
00106 variable pi
00107 #
00108 # This Bessel function can be expressed in terms of elementary
00109 # functions. Therefore use the explicit formula
00110 #
00111 if { $x != 0.0 } {
00112 expr {sqrt(2.0/$pi/$x)*sin($x)}
00113 } else {
00114 return 0.0
00115 }
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125 ret ::math::special::J-1/2 (type x) {
00126 variable pi
00127 if { $x == 0.0 } {
00128 return -code error "Argument must not be zero (singularity)"
00129 } else {
00130 return [expr {-cos($x)/sqrt($pi*$x/2.0)}]
00131 }
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 namespace ::math::special {}
00146
00147 ret ::math::special::I_n (type n , type x) {
00148 if { ! [string is integer $n] || $n < 0 } {
00149 error "Wrong order: must be positive integer or zero"
00150 }
00151
00152 set n2 [expr {$n+8}] ;# Note: just a guess that this will be enough
00153
00154 set ynp1 0.0
00155 set yn 1.0
00156 set sum 1.0
00157
00158 while { $n2 > 0 } {
00159 set ynm1 [expr {$ynp1+2.0*$n2*$yn/$x}]
00160 set sum [expr {$sum+$ynm1}]
00161 if { $n2 == $n+1 } {
00162 set result $ynm1
00163 }
00164 set ynp1 $yn
00165 set yn $ynm1
00166 incr n2 -1
00167 }
00168
00169 set quotient [expr {(2.0*$sum-$ynm1)/exp($x)}]
00170
00171 expr {$result/$quotient}
00172 }
00173
00174
00175
00176
00177 if { 0 } {
00178 tcl = _precision 17
00179 foreach x {0.0 2.0 4.4 6.0 10.0 11.0 12.0 13.0 14.0} {
00180 puts "J0($x) = [::math::special::J0 $x] - J1($x) = [::math::special::J1 $x] \
00181 - J1/2($x) = [::math::special::J1/2 $x]"
00182 }
00183 foreach n {0 1 2 3 4 5} {
00184 puts [::math::special::I_n $n 1.0]
00185 }
00186 }
00187