1

I'm building a program that converts orbital elements into cartesian coordinates.

I want to create a function that does this, converts orbital elements into cartisian coordinates, but I can't get it to work. This is my first time using fortran so I'm still getting used to it.

program conversion

implicit none
real*8 :: EC, A, IC, OM, W, TA, X, Y, Z
real*8, external :: XCARTISIAN, YCARTISIAN, ZCARTISIAN, r

print *, "Insert Oribtal Elements (EC, A, IC, OM, W, TA): "
read *, EC, A, IC, OM, W, TA, X, Y, Z


X = XCARTISIAN(EC, A, IC, OM, W, TA)
Y = YCARTISIAN(EC, A, IC, OM, W, TA)
Z = ZCARTISIAN(EC, A, IC, OM, W, TA)

print *, "X : ", X, "Y : ", Y, "Z : ", Z

end program conversion



real*8 function XCARTISIAN(EC, A, IC, OM, W, TA)

implicit none
real*8, intent(in) :: EC, A, IC, OM, W, TA
real*8 :: XCARTISIAN, r

r = A(1-EC**2)/(1+EC*COS(TA))
XCARTISIAN = r(COS(OM)*COS(W+TA)-SIN(OM)*SIN(W+TA)*COS(IC))

return

end function XCARTISIAN

real*8 function YCARTISIAN(EC, A, IC, OM, W, TA)

implicit none
real*8, intent(in) :: EC, A, IC, OM, W, TA
real*8 :: YCARTISIAN

r = A(1-EC**2)/(1+EC*COS(TA))
YCARTISIAN = r(SIN(OM)*COS(W+TA)+COS(OM)*SIN(W+TA)*COS(IC))

return

end function YCARTISIAN


real*8 function ZCARTISIAN(EC, A, IC, OM, W, TA)

implicit none
real*8, intent(in) :: EC, A, IC, OM, W, TA
real*8 :: ZCARTISIAN

r = A(1-EC**2)/(1+EC*COS(TA))
ZCARTISIAN = r(SIN(W+F)*SIN(IC)

return

end function ZCARTISIAN

How can I get this to work and make a single function that does this instead of three separate ones for X, Y and Z individually?

The conversion formulas are as follows:

X = r(COS(OM)*COS(W+TA)-SIN(OM)*SIN(W+TA)*COS(IC))
Y = r(SIN(OM)*COS(W+TA)+COS(OM)*SIN(W+TA)*COS(IC))
Z = r(SIN(W+F)*SIN(IC)

where,

r = A(1-EC**2)/(1+EC*COS(TA))

2 Answers2

1

Maybe Put your functions into a module?

MODULE ORBITCANDY 
IMPLICIT NONE
PRIVATE

TYPE(Cart_typ)
  REAL*8 X
  REAL*8 Y
  REAL*8 Z
END TYPE Cart_typ
PUBLIC :: Cart_Typ

TYPE(OE_typ)
  REAL*8 EC
  REAL*8 A
  REAL*8 IC
  REAL*8 OM
  REAL*8 W
  REAL*8 TA
END TYPE OE_typ
PUBLIC :: OE_Typ

PUBLIC :: OE2CART

CONTAINS

function OE2Cart(OE)
implicit none
TYPE(OE_Typ) , INTENT(IN   ) :: OE
TYPE(Cart_Typ)               :: OE2Cart
real*8                       :: EC, A, IC, OM, W, TA
real*8                       :: XCARTISIAN, r

EC = OE%EC
A  = OE%A
IC = OE%IC
OM = OE%OM
W  = OE%W
TA = OE%TA
OE2Cart%X = XCARTISIAN(EC, A, IC, OM, W, TA)
OE2Cart%Y = YCARTESIAN(EC, A, IC, OM, W, TA)
OE2Cart%Z = ZCARTESIAN(EC, A, IC, OM, W, TA)

RETURN
END FUNCTION OE2CART

!%%%%%%%%%%%%%%
real*8 function YCARTISIAN(EC, A, IC, OM, W, TA)
implicit none
TYPE(OE_Typ) , INTENT(IN   ) :: OE
real*8, intent(in) :: EC, A, IC, OM, W, TA
real*8 :: XCARTISIAN, r

r = A(1-EC**2)/(1+EC*COS(TA))
XCARTISIAN = r(COS(OM)*COS(W+TA)-SIN(OM)*SIN(W+TA)*COS(IC))

return
end function XCARTISIAN

!%%%%%%%%%%%%%%
real*8 function YCARTISIAN(EC, A, IC, OM, W, TA)
implicit none
real*8, intent(in) :: EC, A, IC, OM, W, TA
real*8 :: YCARTISIAN

r = A(1-EC**2)/(1+EC*COS(TA))
YCARTISIAN = r(SIN(OM)*COS(W+TA)+COS(OM)*SIN(W+TA)*COS(IC))

return
end function YCARTISIAN


   !%%%%%%%%%%%%%%
real*8 function ZCARTISIAN(EC, A, IC, OM, W, TA)

implicit none
real*8, intent(in) :: EC, A, IC, OM, W, TA
real*8 :: ZCARTISIAN

r = A(1-EC**2)/(1+EC*COS(TA))
ZCARTISIAN = r(SIN(W+F)*SIN(IC)

return

end function ZCARTISIAN

END MODULE ORBITCANDY 

And one for R, and then CART2GEODETIC, Etc...

program conversion
USE ORBITCANDY
implicit none
TYPE(OE_Typ)   :: OE
TYPE(Cart_Typ) :: Cart
real*8, external :: r ! Add this one above

print *, "Insert Oribtal Elements (EC, A, IC, OM, W, TA): "
read *, OE%EC, OE%A, OE%IC, OE%OM, OE%W, OE%TA

print *, "Insert Oribtal Elements (EC, A, IC, OM, W, TA): "
read *, OE%EC, OE%A, OE%IC, OE%OM, OE%W, OE%TA

XYZ = OE2CART(OE)
print *, "X : ", XYZ%X, "Y : ", XYZ%Y, "Z : ", XYZ%Z

end program conversion

There is no compiler in the iPad, so I am sure to have a typo...

Holmz
  • 714
  • 7
  • 14
  • 2
    Why does seemingly simple Fortran make my eyes bleed each time again? – rubenvb Nov 16 '16 at 12:43
  • Baby steps @rubenvb but the program (main) looks simpler. I could put ISO_C_BINDING in so you could use it with C (?). – Holmz Nov 16 '16 at 12:45
1

The most straightforward thing to do is to make a single subroutine. Best placed in a module, but that is optional (But IMHO all functions and subroutines should be in some module).

subroutine XYZCARTISIAN(XCARTISIAN, YCARTISIAN, ZCARTISIAN, EC, A, IC, OM, W, TA)

  implicit none
  real*8 :: XCARTISIAN, YCARTISIAN, ZCARTISIAN
  real*8, intent(in) :: EC, A, IC, OM, W, TA
, r

  r = A(1-EC**2)/(1+EC*COS(TA))

  XCARTISIAN = r*(COS(OM)*COS(W+TA)-SIN(OM)*SIN(W+TA)*COS(IC))
  YCARTISIAN = r*(SIN(OM)*COS(W+TA)+COS(OM)*SIN(W+TA)*COS(IC))
  ZCARTISIAN = r*(SIN(W+F)*SIN(IC)
end subroutine

This will also be faster, because you compute r only once and you make just one sub-program call.

Please note:

  1. real*8 is completely non-standard, it is not Fortran.
  2. Use indentation to make your code more readable.
  3. No return is necessary there, us it only to return prematurely.