Blame view

src/idl_extern/CMTotal_for_Dustemwrap/litmsol.pro 12.1 KB
517b8f98   Annie Hughes   first commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
;+
; NAME:
;   LITMSOL
;
; AUTHOR:
;   Craig B. Markwardt, NASA/GSFC Code 662, Greenbelt, MD 20770
;   craigm@lheamail.gsfc.nasa.gov
;   UPDATED VERSIONs can be found on my WEB PAGE: 
;      http://cow.physics.wisc.edu/~craigm/idl/idl.html
;
; PURPOSE:
;   Solve the light-time equation between two moving bodies
;
; MAJOR TOPICS:
;   Geometry, Physics
;
; CALLING SEQUENCE:
;   LITMSOL, T1, X1, Y1, Z1, T2, INFO2, RAW2, OBJ2, INFOSUN, RAWSUN, $
;            /RECEIVER, TBASE=, TOLERANCE=, POSUNITS=, MAXITER=, $
;            /NO_SHAPIRO
;
; DESCRIPTION:
;
;  The procedure LITMSOL solves the light time equation between two
;  moving bodies in the solar system.  Given the time and position of
;  reception or transmission of a photon, this equation determines the
;  time of transmission or reception at the other solar system body.
;  Since both bodies may be moving, the equation must be solved
;  iteratively.
;
;  The trajectories of solar system bodies must be described by either
;  a JPL ephemeris, or by a JPL-like ephemeris generated by
;  JPLEPHMAKE.  This routine calls JPLEPHINTERP.
;
;  The user specifies the known time and position of interaction as
;  T1, X1, Y1 and Z1, in units of POSUNITS.  The time of interaction
;  at the other body -- the solution to the light time equation -- is
;  returned as T2.  If the photon was *received* at time T1, then the
;  RECEIVER keyword should be set (in which case the transmission must
;  have occurred in the past).
;
;  Since the solution is iterative, the user may specify a solution
;  tolerance, and a maximum number of iterations.
;
;  If users wish to include the Shapiro time delay, which has a
;  maximum amplitude of approximately 250 usec, they must specify the
;  ephemeris of the Sun (INFOSUN, RAWSUN).  The Shapiro delay is the
;  extra general relativistic delay caused by the Sun's potential.
;
;
; INPUTS:
;
;   T1 - epoch of interaction, in Julian days, in the TDB timescale.
;        (scalar or vector)
;
;   X1, Y1, Z1 - coordinates of interaction, referred to the solar
;                system barycenter, in J2000 coordinates.  Units are
;                described by POSUNITS. (scalar or vector)
;
;   INFO2, RAW2 - ephemeris of other solar system body, returned by
;                 JPLEPHREAD or JPLEPHMAKE.
;
;   INFOSUN, RAWSUN - ephemeris of at least the Sun, as returned by
;                     JPLEPHREAD.  Only used of NO_SHAPIRO is not set.
;
;
; OUTPUTS:
;
;   T2 - upon output, epoch of interaction at the second solar system
;        body, in Julian days, in the TDB timescale.
;
;
; KEYWORD PARAMETERS:
;
;   RECEIVER - if set, then the epoch T1 is a reception of a photon.
;              Otherwise T1 is the epoch of transmission of a photon.
;
;   VX1, VY1, VZ1 - upon input, the body velocity at time T1, in
;                   VELUNITS units.  This information is required only
;                   if the SHAPIRO_DERIV is required.
;
;   X2, Y2, Z2 - upon return, the body position at time T2, in
;                POSUNITS units.
;   VX2, VY2, VZ2 - upon return, the body velocity at time T2, in
;                VELUNITS units.
;
;   TBASE - a fixed epoch time (Julian days) to be added to each value
;           of T1.  Since subtraction of large numbers occurs with
;           TBASE first, the greatest precision is achieved when TBASE
;           is expressed as a nearby julian epoch, T1 is expressed
;           as a small offset from the fixed epoch.  
;           Default: 0
;
;   POSUNITS - the units for positions, one of 'CM', 'KM', 'LT-S' or
;              'AU'.
;              Default: 'CM'
;   VELUNITS - the units for velocities (and Shapiro derivative).
;              Default: POSUNITS+'/S'
;
;   TOLERANCE - the solution tolerance, expressed in POSUNITS.
;               Default: 1000 CM
;
;   ERROR - upon return, a vector giving the estimated error in the
;           solution for each point, expressed in POSUNITS.  This
;           quantity should be less than TOLERANCE unless the number
;           of iterations exceeded MAXITER.
;
;   MAXITER - maximum number of solution iterations to be taken.
;             Default: 5
;   NITER - upon return, contains the actual number of iterations used.
;
;   SHAPIRO_CALC - method of calculating Shapiro delay, a string with
;                  one value of 'NONE', 'DELAY' or 'BOTH'.  NONE means
;                  do not calculate any Shapiro delay values.  DELAY
;                  means calculate Shapiro delay only.  BOTH means
;                  calculate the delay *and* its derivative with
;                  respect to time.  If SHAPIRO_CALC is set to
;                  DELAY or BOTH, then INFOSUN and RAWSUN must be
;                  specified.  If BOTH, then VX1, VY1 and VZ1 must
;                  also be specified. This keyword overrides
;                  NO_SHAPIRO.
;   NO_SHAPIRO - if set, then the Shapiro delay will not be accounted
;                for.  Use SHAPIRO_CALC instead.
;   SHAPIRO_DELAY - upon return, contains the Shapiro delay in
;                   seconds, if SHAPIRO_CALC is set to 'DELAY' or
;                   'BOTH'.
;   SHAPIRO_DERIV - upon return, contains the derivative of the
;                   Shapiro delay, in light seconds per time unit of
;                   velocity (SHAPIRO_CALC must be set to 'BOTH' to
;                   enable this calculation).  Note that you must
;                   supply VX1, VY1 and VZ1 to get the derivative
;                   value.
;
;
; EXAMPLE:
;
;
;
; SEE ALSO:
;
;   JPLEPHREAD, JPLEPHINTERP
;
;
; MODIFICATION HISTORY:
;   Written, 6 May 2002, CM
;   Documented, 12 May 2002, CM
;   Added TGUESS keyword, 29 May 2002, CM
;   Added ERROR and X/Y/ZOFF keywords, 25 Sep 2002, CM
;   Extensive revisions: addition of SHAPIRO_{CALC,DELAY,DERIV}
;     values; input VX1, VY1 and VZ1; output X2, Y2, Z2 and VX2 VY2
;     and VZ2; and VELUNITS keyword, 07 Mar 2007, CM
;   Allow user specified function to interpolate INFO2/RAW2 via
;     INTERP_FUNC keyword, 09 Oct 2008, CM
;
;  $Id: litmsol.pro,v 1.7 2008/10/10 00:50:19 craigm Exp $
;
;-
; Copyright (C) 2002, 2007, 2008, Craig Markwardt
; This software is provided as is without any warranty whatsoever.
; Permission to use, copy, modify, and distribute modified or
; unmodified copies is granted, provided this copyright and disclaimer
; are included unchanged.
;-

pro litmsol, t1, x1, y1, z1, t2, info2, raw2, obj2, info, raw, $
             tbase=tbase, tolerance=tol0, posunits=posunits0, $
             receiver=receiver, maxiter=maxiter0, no_shapiro=noshap, $
             tguess=tguess, error=diff, niter=i, $
             shapiro_delay=shdelay, shapiro_deriv=shderiv, shapiro_calc=shcalc0, $
             vx1=vx1, vy1=vy1, vz1=vz1, velunits=velunits0, $
             x2=x2, y2=y2, z2=z2, vx2=vx2, vy2=vy2, vz2=vz2, $
             xoffset=xoff, yoffset=yoff, zoffset=zoff, $
             interp_func=intfunc0

  if n_elements(shcalc0) GT 0 then begin
      shcalc = strupcase(strtrim(shcalc0(0),2))
      if shcalc NE 'NONE' AND shcalc NE 'BOTH' AND $
         shcalc NE 'DELAY' then $
        message, 'ERROR: SHAPIRO_CALC value of "'+shcalc+'" was invalid.'
      if keyword_set(noshap) AND shcalc NE 'NONE' then $
        message, 'ERROR: SHAPIRO_CALC and NO_SHAPIRO did not agree.'
  endif else begin
      shcalc = 'DELAY'
      if keyword_set(noshap) then shcalc = 'NONE'
  endelse
      
  ;; Default position and velocity units
  if n_elements(posunits0) EQ 0 then begin
      posunits = 'CM'
  endif else begin
      posunits = strtrim(posunits0(0),1)
  endelse
  if n_elements(velunits0) EQ 0 then begin
      velunits=posunits+'/S'
  endif else begin
      velunits = strtrim(velunits0(0),1)
  endelse

  ;; Default tolerances
  if n_elements(tol0) EQ 0 then begin
      tol = 1000d     ;; 10 m tolerance
      posunits = 'CM'
  endif else begin
      tol = tol0(0)
  endelse

  ;; Default interpolation function: JPLEPHINTERP
  if n_elements(intfunc0) EQ 0 then begin
      intfunc = 'JPLEPHINTERP'
  endif else begin
      intfunc = strtrim(strupcase(intfunc0(0)),2)
  endelse

  if n_elements(xoff) EQ 0 then xoff = 0d
  if n_elements(yoff) EQ 0 then yoff = 0d
  if n_elements(zoff) EQ 0 then zoff = 0d

  if n_elements(maxiter0) EQ 0 then maxiter = 5L $
  else                              maxiter = floor(maxiter0(0))>2
      
  case posunits of 
      'CM':   clight = info2.c*1d2  ;; CM/S
      'KM':   clight = info2.c*1d-3 ;; KM/S
      'LT-S': clight = 1d           ;; LT-S/S
      'AU':   clight = 1d/info2.au  ;; AU/S
  endcase

  ;; Decide whether to compute derivative of shapiro delay
  if shcalc EQ 'BOTH' then begin
      calcvel = 1

      if n_elements(vx1) EQ 0 OR n_elements(vy1) EQ 0 OR $
        n_elements(vz1) EQ 0 then begin
          message, 'ERROR: You must specify VX1,VY1,VZ1 when computing '+$
            'the Shapiro derivative'
      endif
  endif
  if arg_present(vx2) OR arg_present(vy2) OR arg_present(vz2) then calcvel = 1

  ;; If any Shapiro calculations are required, pre-compute r1dot
  if shcalc NE 'NONE' then begin
      jplephinterp, info, raw, t1, xs, ys, zs, /sun, $
        velocity=calcvel, vxs, vys, vzs, $
        posunits=posunits, velunits=velunits, tbase=tbase
      r1 = sqrt((x1-xs)^2 + (y1-ys)^2 + (z1-zs)^2)
      if shcalc EQ 'BOTH' then $
        r1dot = ((x1-xs)*(vx1-vxs)+(y1-ys)*(vy1-vys)+(z1-zs)*(vz1-vzs))/r1
  endif

  ;; Use TGUESS if provided, otherwise estimate T2 as T1 to begin with
  dt0 = t1*0
  if n_elements(tguess) EQ n_elements(t1) then begin
      t2 = tguess 
      dtold = abs(tguess-t1)*86400d
      if keyword_set(receiver) then dtold = -dtold
  endif else begin
      t2 = t1
      dtold = 0d
  endelse


  ;; ==================== BEGIN ITERATION
  ct = 1L
  i = 0L
  while (ct GT 0) AND (i LT maxiter) do begin

      ;; Position and vel of body at estimated time T2
      call_procedure, intfunc, info2, raw2, t2, x2, y2, z2, objectname=obj2, $
        velocity=calcvel, vx2, vy2, vz2, $
        tbase=tbase, posunits=posunits, velunits=velunits

      ;; Compute distance from T1 to T2 in physical and light-second units
      dr = sqrt((x1-(x2+xoff))^2 + (y1-(y2+yoff))^2 + (z1-(z2+zoff))^2)
      dt = dr / clight

      ;; Add Shapiro delay
      if shcalc NE 'NONE' then begin

          ;; First iteration: recompute time of sun position, since
          ;; the actual sun position at time of closest approach will
          ;; be slightly different
          if i EQ 1 then begin
              ts = t1

              ;; Angle between S/C and sun, as seen from earth
              cos_th = ((x2-x1)*(xs-x1) + (y2-y1)*(ys-y1) + (z2-z1)*(zs-z1))/dr/r1
              whc = where(cos_th GT 0, ctc)
              ;; Correct for the light travel time to the time of
              ;; closest approach
              if ctc GT 0 then ts(whc) = (t1 + r1*cos_th/clight/86400d)(whc)

              ;; Recompute the sun position
              jplephinterp, info, raw, ts, xs, ys, zs, /sun, $
                velocity=calcvel, vxs, vys, vzs, $
                posunits=posunits, velunits=velunits, tbase=tbase
              r1 = sqrt((x1-xs)^2 + (y1-ys)^2 + (z1-zs)^2)
              if shcalc EQ 'BOTH' then $
                r1dot = ((x1-xs)*(vx1-vxs)+(y1-ys)*(vy1-vys)+(z1-zs)*(vz1-vzs))/r1
          endif

          
          ;; Compute Shapiro delay
          dt0 = 2*info.msol
          ;; Body-sun distance
          r2 = sqrt((x2-xs)^2 + (y2-ys)^2 + (z2-zs)^2)
          rsump = (r1+r2+dr+dt0*clight)
          rsumm = (r1+r2-dr+dt0*clight)
          shdelay = dt0*alog(rsump/rsumm)
          dt = dt + shdelay

          ;; Compute derivative of Shapiro delay
          if shcalc EQ 'BOTH' then begin
              r2dot = ((x2-xs)*(vx2-vxs)+(y2-ys)*(vy2-vys)+(z2-zs)*(vz2-vzs))/r2
              drdot = ((x2-x1)*(vx2-vx1)+(y2-y1)*(vy2-vy1)+(z2-z1)*(vz2-vz1))/dr
              shderiv = 2*dt0*(((r1+r2+dt0*clight)*drdot - (r1dot+r2dot)*dr) / $
                               (rsump*rsumm))
          endif
      endif

      ;; If 1 <-> 2 are switched, then reverse sign of DT
      if keyword_set(receiver) then dt = -dt

      ;; Correct T2 and compute how much change from previous iteration
      t2 = t1 + dt/86400d
      diff = abs(dtold-dt)*clight
      wh = where(diff GT tol, ct)

      ;; Prepare for next iteration
      dtold = dt
      i = i + 1
  endwhile

  return
end