Single file access functions — CALCEPH - Fortran 77/90/95 language 3.4.1 documentation

# Single file access functions

This group of functions works on a single ephemeris file at a given instant. They use an internal global variable to store information about the current opened ephemeris file.

They are provided to have a similar interface of the fortran PLEPH function, supplied with the JPL ephemeris files. So the following call to PLEPH

    PLEPH(46550D0, 3, 12, PV)

could be replaced by

    calceph_sopen("ephemerisfile.dat")
    calceph_scompute(46550D0, 0, 3, 12, PV)
    calceph_sclose()

While the function PLEPH could access only one file in a program, these functions could access on multiple files in a program but not at same time. To access multiple files at a same time, the functions listed in the section Multiple file access functions must be used.

When an error occurs, these functions execute error handlers according to the behavior defined by the function `f90calceph_seterrorhandler()`.

The python interface does not provide these functions, the listed in the section Multiple file access functions must be used.

## Thread notes

If the standard I/O functions such as fread are not reentrant then the CALCEPH I/O functions using them will not be reentrant either.

If the library was configured with the option --enable-thread=yes, these functions use an internal global variable per thread. Each thread could access to different ephemeris file and compute ephemeris data at same time. But each thread must call the function `f90calceph_sopen()` to open ephemeris file even if all threads work on the same file.

If the library was configured with the default option --enable-thread=no, these functions use an internal global variable per process and are not thread-safe. If multiple threads are used in the process and call the function `f90calceph_scompute()` at the same time, the caller thread must surround the call to this function with locking primitives, such as pthread_lock/pthread_unlock if POSIX Pthreads are used.

## Usage

The following examples, that can be found in the directory examples of the library sources, show the typical usage of this group of functions.

The example in Fortran 77/90/95 language is `f77single.f`.

    program f77single
        implicit none
        include 'f90calceph.h'
        integer res
        double precision AU, EMRAT, GM_Mer
        double precision jd0
        double precision dt
        double precision PV(6)
        integer j
        double precision valueconstant
        character(len=CALCEPH_MAX_CONSTANTNAME) nameconstant

        jd0 = 2442457
        dt = 0.5E0
        ! open the ephemeris file
        res = f90calceph_sopen("example1.dat")
        if (res.eq.1) then
            write (*,*) "The ephemeris is already opened"
            ! print the values of AU, EMRAT and GM_Mer
            if (f90calceph_sgetconstant("AU", AU).eq.1) then
                write (*,*) "AU=", AU
            endif
            if (f90calceph_sgetconstant("EMRAT", EMRAT).eq.1) then
                write (*,*) "EMRAT=", EMRAT
            endif
            if (f90calceph_sgetconstant("GM_Mer", GM_Mer).eq.1)then
                write (*,*) "GM_Mer=", GM_Mer
            endif

           ! compute and print the coordinates
           ! the geocentric moon coordinates
           res = f90calceph_scompute(jd0, dt, 10, 3, PV)
           call printcoord(PV,"geocentric coordinates of the Moon")
           ! the value TT-TDB
           if (f90calceph_scompute(jd0, dt, 16, 0, PV).eq.1) then
            write (*,*) "TT-TDB = ", PV(1)
           endif
           ! the heliocentric coordinates of Mars
           res = f90calceph_scompute(jd0, dt, 4, 11, PV)
           call printcoord(PV,"heliocentric coordinates of Mars")

          ! print the whole list of the constants
          write (*,*) "list of constants"
          do j=1, f90calceph_sgetconstantcount()
             res = f90calceph_sgetconstantindex(j,nameconstant,valueconstant)
             write (*,*) nameconstant,"=",valueconstant
          enddo

          ! close the ephemeris file
          call f90calceph_sclose
          write (*,*) "The ephemeris is already closed"
         else
            write (*,*) "The ephemeris can't be opened"
         endif
    stop
    end

## Functions

### f90calceph_sopen

function `f90calceph_sopen`(filename)

  Parameters: | filename [CHARACTER(len=*), intent(in)] :: pathname of the file.
  Return: | f90calceph_sopen [INTEGER] :: 0 if an error occurs, otherwise non-zero value.

This function opens the file whose pathname is the string pointed to by filename, reads the header of this file and associates an ephemeris descriptor to an internal variable. This file must be an ephemeris file.

This file must be compliant to the format specified by the 'original JPL binary' , 'INPOP 2.0 binary' or 'SPICE' ephemeris file. At the moment, supported SPICE files are the following :

> - text Planetary Constants Kernel (KPL/PCK) files
> - binary PCK (DAF/PCK) files.
> - binary SPK (DAF/SPK) files containing segments of type 1, 2, 3, 5, 8, 9, 12, 13, 17, 18, 20, 21, 102, 103 and 120.
> - meta kernel (KPL/MK) files.
> - frame kernel (KPL/FK) files. Only a basic support is provided.

The function `f90calceph_sclose()` must be called to free allocated memory by this function.

The following example opens the ephemeris file example1.dat

    integer res
    res = f90calceph_sopen("example1.dat")
    if (res.eq.1) then
         ! ...  computation ...
    endif
    call f90calceph_sclose

### f90calceph_scompute

function `f90calceph_scompute`(JD0, time, target, center, PV)

  Parameters: | JD0 [REAL(8), intent(in)] :: Integer part of the Julian date time [REAL(8), intent(in)] :: Fraction part of the Julian date target [INTEGER, intent(in)] :: The body or reference point whose coordinates are required (see the list, below). center [INTEGER, intent(in)] :: The origin of the coordinate system (see the list, below). If target is 14, 15, 16 or 17 (nutation, libration, TT-TDB or TCG-TCB), center must be 0. PV (6) [REAL(8), intent(out) :: Depending on the target value, an array to receive the cartesian position (x,y,z) and the velocity (xdot, ydot, zdot), or a time scale transformation value, or the angles of the librations of the Moon and their derivatives, or the nutation angles and their derivatives.
  Return: | f90calceph_scompute [INTEGER] :: 0 if an error occurs, otherwise non-zero value.

This function reads, if needed, and interpolates a single object, usually the position and velocity of one body (target) relative to another (center), from the ephemeris file, previously opened with the function `f90calceph_sopen()`, for the time JD0+time and stores the results to PV.

To get the best precision for the interpolation, the time is splitted in two floating-point numbers. The argument JD0 should be an integer and time should be a fraction of the day. But you may call this function with time=0 and JD0, the desired time, if you don't take care about precision.

The possible values for target and center are :

value | meaning
--- | ---
1 | Mercury Barycenter
2 | Venus Barycenter
3 | Earth
4 | Mars Barycenter
5 | Jupiter Barycenter
6 | Saturn Barycenter
7 | Uranus Barycenter
8 | Neptune Barycenter
9 | Pluto Barycenter
10 | Moon
11 | Sun
12 | Solar Sytem barycenter
13 | Earth-moon barycenter
14 | Nutations
15 | Librations
16 | TT-TDB
17 | TCG-TCB
asteroid number + CALCEPH_ASTEROID | asteroid

These accepted values by this function are the same as the value for the JPL function PLEPH, except for the values TT-TDB, TCG-TCB and asteroids.

For example, the value "CALCEPH_ASTEROID+4" for target or center specifies the asteroid Vesta.

The following example prints the heliocentric coordinates of Mars at time=2451624.5 and at 2451624.9

    double precision PV(6)
    integer res
    double precision jd0
    double precision dt1, dt2

    jd0 = 2442457
    dt  = 0.5D0
    dt2 = 0.9D0

    res = f90calceph_sopen("example1.dat")
    if (res.eq.1) then

       ! the heliocentric coordinates of Mars
       res = f90calceph_scompute(jd0, dt1, 4, 11, PV)
       write (*,*) PV

       res = f90calceph_scompute(jd0, dt2, 4, 11, PV)
       write (*,*) PV

      call f90calceph_sclose
    endif

### f90calceph_sgetconstant

function `f90calceph_sgetconstant`(name, value)

  Parameters: | name [CHARACTER(len=*), intent(in)] :: name of the constant value [REAL(8), intent(out)] :: first value of the constant
  Return: | f90calceph_sgetconstant [INTEGER] :: 0 if an error occurs, otherwise non-zero value.

This function returns the value associated to the constant name in the header of the ephemeris file.

Only the first value is returned if multiple values are associated to a constant, such as a list of values.

The function `f90calceph_sopen()` must be previously called before.

The following example prints the value of the astronomical unit stored in the ephemeris file

    integer res
    double precision AU

    res = f90calceph_sopen("example1.dat")
    if (res.eq.1) then
        if (f90calceph_sgetconstant("AU", AU).eq.1) then
            write (*,*) "AU=", AU
        endif
     endif

### f90calceph_sgetconstantcount

function `f90calceph_sgetconstantcount`()

  Return: | f90calceph_prefetch :: 0 if an error occurs, otherwise non-zero value.

This function returns the number of constants available in the header of the ephemeris file.

The function `f90calceph_sopen()` must be previously called before.

The following example prints the number of available constants stored in the ephemeris file

    integer res
    integer n
    ! open the ephemeris file
    res = f90calceph_sopen("example1.dat")
    if (res.eq.1) then

        n = f90calceph_sgetconstantcount()
        write (*,*) "number of constants", n

        call f90calceph_sclose
    endif

### f90calceph_sgetconstantindex

function `f90calceph_sgetconstantindex`(index, name, value)

  Parameters: | index [INTEGER, intent(in)] :: index of the constant, between 1 and `f90calceph_getconstantcount()` name [CHARACTER(len=CALCEPH_MAX_CONSTANTNAME), intent(out)] :: name of the constant value [REAL(8), intent(out)] :: first value of the constant
  Return: | f90calceph_sgetconstantindex [INTEGER] :: 0 if an error occurs, otherwise non-zero value.

This function returns the name and its value of the constant available at the specified index in the header of the ephemeris file. The value of index must be between 1 and `f90calceph_sgetconstantcount()`.

Trailing blanks are added to the name of the constant.

The function `f90calceph_sopen()` must be previously called before.

The following example displays the name of the constants, stored in the ephemeris file, and their values

    integer res
    integer j
    double precision valueconstant
    character(len=CALCEPH_MAX_CONSTANTNAME) nameconstant

    res = f90calceph_sopen("example1.dat")
    if (res.eq.1) then

      do j=1, f90calceph_sgetconstantcount()
         res = f90calceph_sgetconstantindex(j,nameconstant,valueconstant)
         write (*,*) nameconstant,"=",valueconstant
      enddo

      call f90calceph_sclose
    endif

### f90calceph_sgetfileversion

function `f90calceph_sgetfileversion`(version)

  Parameters: | version [CHARACTER(len=CALCEPH_MAX_CONSTANTVALUE), intent(out)] :: version of the file
  Return: | f90calceph_sgetfileversion [INTEGER] :: returns 0 if the file version was not found, otherwise non-zero value.

This function returns the version of the ephemeris file, as a string. For example, the argument version will contain 'INPOP10B', 'EPM2017' or 'DE405', ... .

If the file is an original JPL binary planetary ephemeris, then the version of the file can always be determined. If the file is a spice kernel, the version of the file is retrieved from the constant INPOP_PCK_VERSION, EPM_PCK_VERSION, or PCK_VERSION.

The function `f90calceph_sopen()` must be previously called before.

The following example prints the version of the ephemeris file.

    integer res
    character(len=CALCEPH_MAX_CONSTANTVALUE) version
    ! open the ephemeris file
    res = f90calceph_sopen("example1.dat")
    if (res.eq.1) then

      res = f90calceph_sgetfileversion(version)
      write (*,*) "The version of the file is ", version

      call f90calceph_sclose
    endif

### f90calceph_sgettimescale

function `f90calceph_sgettimescale`()

  Return: | f90calceph_sgettimescale [INTEGER] :: 0 if an error occurs, otherwise non-zero value.

This function returns the timescale of the ephemeris file :
  - 1 if the quantities of all bodies are expressed in the TDB time scale.
  - 2 if the quantities of all bodies are expressed in the TCB time scale.

The function `f90calceph_sopen()` must be previously called before.

The following example prints the time scale available in the ephemeris file

    integer res
    integer t
    ! open the ephemeris file
    res = f90calceph_sopen("example1.dat")
    if (res.eq.1) then

        t = f90calceph_sgettimescale()
        write (*,*) "timescale ", t

        call f90calceph_sclose
    endif

### f90calceph_sgettimespan

function `f90calceph_sgettimespan`(firsttime, lasttime, continuous)

  Parameters: | firsttime [REAL(8), intent(out)] :: Julian date of the first time lasttime [REAL(8), intent(out)] :: Julian date of the last time continuous [INTEGER, intent(out)] :: information about the availability of the quantities over the time span
  Return: | f90calceph_sgettimespan [INTEGER] :: 0 if an error occurs, otherwise non-zero value.

This function returns the first and last time available in the ephemeris file. The Julian date for the first and last time are expressed in the time scale returned by `f90calceph_sgettimescale()` .

It returns the following value in the parameter continuous :

> - 1 if the quantities of all bodies are available for any time between the first and last time.
> - 2 if the quantities of some bodies are available on discontinuous time intervals between the first and last time.
> - 3 if the quantities of each body are available on a continuous time interval between the first and last time, but not available for any time between the first and last time.

The function `f90calceph_sopen()` must be previously called before.

The following example prints the first and last time available in the ephemeris file

    integer res
    integer cont
    double precision  jdfirst, jdlast
    ! open the ephemeris file
    res = f90calceph_sopen("example1.dat")
    if (res.eq.1) then

      res = f90calceph_sgettimespan(jdfirst, jdlast, cont)
      write (*,*) "data available between ", jdfirst, "and", jdlast
      write (*,*) "continuous data ", cont

        call f90calceph_sclose
    endif

### f90calceph_sclose

subroutine `f90calceph_sclose`()

This function closes the ephemeris data file and frees allocated memory by the function `f90calceph_sopen()`.