orbel_xv2el.f 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. ***********************************************************************
  2. c ORBEL_XV2EL.F
  3. ***********************************************************************
  4. * PURPOSE: Given the cartesian position and velocity of an orbit,
  5. * compute the osculating orbital elements.
  6. *
  7. C input:
  8. c x,y,z ==> position of object (real scalars)
  9. c vx,vy,vz ==> velocity of object (real scalars)
  10. c gmsum ==> G*(M1+M2) (real scalar)
  11. c
  12. c Output:
  13. c ialpha ==> conic section type ( see PURPOSE, integer scalar)
  14. C a ==> semi-major axis or pericentric distance if a parabola
  15. c (real scalar)
  16. c e ==> eccentricity (real scalar)
  17. C inc ==> inclination (real scalar)
  18. C capom ==> longitude of ascending node (real scalar)
  19. C omega ==> argument of perihelion (real scalar)
  20. C capm ==> mean anomoly(real scalar)
  21. c
  22. * ALGORITHM: See e.g. p.70 of Fitzpatrick's "Priciples of Cel. Mech."
  23. * REMARKS: If the inclination INC is less than TINY, we
  24. * arbitrarily choose the longitude of the ascending node LGNODE
  25. * to be 0.0 (so the ascending node is then along the X axis). If
  26. * the eccentricity E is less than SQRT(TINY), we arbitrarily
  27. * choose the argument of perihelion to be 0.
  28. * AUTHOR: M. Duncan.
  29. * DATE WRITTEN: May 8,1992.
  30. * REVISIONS: 12/8/2011
  31. ***********************************************************************
  32. subroutine orbel_xv2el(x,y,z,vx,vy,vz,gmsum,
  33. & ialpha,a,e,inc,capom,omega,capm)
  34. include '../swift.inc'
  35. c... Inputs Only:
  36. real*8 x,y,z,vx,vy,vz,gmsum
  37. c... Outputs
  38. integer ialpha
  39. real*8 a,e,inc,capom,omega,capm
  40. c... Internals:
  41. real*8 hx,hy,hz,h2,h,r,v2,v,vdotr,energy,fac,face,cape,capf,tmpf
  42. real*8 cw,sw,w,u
  43. c----
  44. c... Executable code
  45. * Compute the angular momentum H, and thereby the inclination INC.
  46. hx = y*vz - z*vy
  47. hy = z*vx - x*vz
  48. hz = x*vy - y*vx
  49. h2 = hx*hx + hy*hy +hz*hz
  50. h = sqrt(h2)
  51. if(hz.gt.h) then ! Hal's fix
  52. hz = h
  53. hx = 0.0d0
  54. hy = 0.0d0
  55. endif
  56. inc = acos(hz/h)
  57. * Compute longitude of ascending node CAPOM and the argument of
  58. * latitude u.
  59. fac = sqrt(hx**2 + hy**2)/h
  60. if( (fac.lt. TINY ) .or. (inc.eq.0.0d0) ) then ! Hal's fix
  61. capom = 0.d0
  62. u = atan2(y,x)
  63. if(abs(inc - PI).lt. 10.d0*TINY) u = -u
  64. else
  65. capom = atan2(hx,-hy)
  66. u = atan2 ( z/sin(inc) , x*cos(capom) + y*sin(capom))
  67. endif
  68. if(capom .lt. 0.d0) capom = capom + 2.d0*PI
  69. if(u .lt. 0.d0) u = u + 2.d0*PI
  70. * Compute the radius R and velocity squared V2, and the dot
  71. * product RDOTV, the energy per unit mass ENERGY .
  72. r = sqrt(x*x + y*y + z*z)
  73. v2 = vx*vx + vy*vy + vz*vz
  74. v = sqrt(v2)
  75. vdotr = x*vx + y*vy + z*vz
  76. energy = 0.5d0*v2 - gmsum/r
  77. * Determine type of conic section and label it via IALPHA
  78. if(abs(energy*r/gmsum) .lt. sqrt(TINY)) then
  79. ialpha = 0
  80. else
  81. if(energy .lt. 0.d0) ialpha = -1
  82. if(energy .gt. 0.d0) ialpha = +1
  83. endif
  84. * Depending on the conic type, determine the remaining elements
  85. ***
  86. c ELLIPSE :
  87. if(ialpha .eq. -1) then
  88. a = -0.5d0*gmsum/energy
  89. fac = 1.d0 - h2/(gmsum*a)
  90. if (fac .gt. TINY) then
  91. e = sqrt ( fac )
  92. face =(a-r)/(a*e)
  93. c... Apr. 16/93 : watch for case where face is slightly outside unity
  94. if ( face .gt. 1.d0) then
  95. cape = 0.d0
  96. else
  97. if ( face .gt. -1.d0) then
  98. cape = acos( face )
  99. else
  100. cape = PI
  101. endif
  102. endif
  103. if ( vdotr .lt. 0.d0 ) cape = 2.d0*PI - cape
  104. cw = (cos( cape) -e)/(1.d0 - e*cos(cape))
  105. sw = sqrt(1.d0 - e*e)*sin(cape)/(1.d0 - e*cos(cape))
  106. w = atan2(sw,cw)
  107. if(w .lt. 0.d0) w = w + 2.d0*PI
  108. else
  109. e = 0.d0
  110. w = u
  111. cape = u
  112. endif
  113. capm = cape - e*sin (cape)
  114. omega = u - w
  115. if(omega .lt. 0.d0) omega = omega + 2.d0*PI
  116. omega = omega - int(omega/(2.d0*PI))*2.d0*PI
  117. endif
  118. ***
  119. ***
  120. c HYPERBOLA
  121. if(ialpha .eq. +1) then
  122. a = +0.5d0*gmsum/energy
  123. fac = h2/(gmsum*a)
  124. if (fac .gt. TINY) then
  125. e = sqrt ( 1.d0 + fac )
  126. tmpf = (a+r)/(a*e)
  127. if(tmpf.lt.1.0d0) then
  128. tmpf = 1.0d0
  129. endif
  130. capf = log(tmpf + sqrt(tmpf*tmpf -1.d0))
  131. if ( vdotr .lt. 0.d0 ) capf = - capf
  132. cw = (e - cosh(capf))/(e*cosh(capf) - 1.d0 )
  133. sw = sqrt(e*e - 1.d0)*sinh(capf)/(e*cosh(capf) - 1.d0 )
  134. w = atan2(sw,cw)
  135. if(w .lt. 0.d0) w = w + 2.d0*PI
  136. else
  137. c we only get here if a hyperbola is essentially a parabola
  138. c so we calculate e and w accordingly to avoid singularities
  139. e = 1.d0
  140. tmpf = 0.5d0*h2/gmsum
  141. w = acos(2.d0*tmpf/r -1.d0)
  142. if ( vdotr .lt. 0.d0) w = 2.d0*PI - w
  143. tmpf = (a+r)/(a*e)
  144. capf = log(tmpf + sqrt(tmpf*tmpf -1.d0))
  145. endif
  146. capm = e * sinh(capf) - capf
  147. omega = u - w
  148. if(omega .lt. 0.d0) omega = omega + 2.d0*PI
  149. omega = omega - int(omega/(2.d0*PI))*2.d0*PI
  150. endif
  151. ***
  152. ***
  153. c PARABOLA : ( NOTE - in this case we use "a" to mean pericentric distance)
  154. if(ialpha .eq. 0) then
  155. a = 0.5d0*h2/gmsum
  156. e = 1.d0
  157. w = acos(2.d0*a/r -1.d0)
  158. if ( vdotr .lt. 0.d0) w = 2.d0*PI - w
  159. tmpf = tan(0.5d0 * w)
  160. capm = tmpf* (1.d0 + tmpf*tmpf/3.d0)
  161. omega = u - w
  162. if(omega .lt. 0.d0) omega = omega + 2.d0*PI
  163. omega = omega - int(omega/(2.d0*PI))*2.d0*PI
  164. endif
  165. ***
  166. ***
  167. return
  168. end ! orbel_xv2el
  169. c------------------------------------------------------------------