Partial Derivatives Computation via Autodiff#

In this notebook, we show how to use the autodiff feature of \(\partial\textrm{SGP4}\). Due to the fact that it is written in pytorch, it automatically supports automatic differentiation via torch.autograd.

In this notebook, we show how these partial derivatives can be constructed: for more advanced examples on how to use these gradients for practical applications, see the tutorials on state_transition_matrix_computation, covariance_propagation, graident_based_optimization, orbit_determination.

import dsgp4
import torch

We create a TLE object

#as always, first, we create a TLE object:
tle=[]
tle.append('0 COSMOS 2251 DEB')
tle.append('1 34454U 93036SX  22068.91971155  .00000319  00000-0  11812-3 0  9996')
tle.append('2 34454  74.0583 280.7094 0037596 327.9100  31.9764 14.35844873683320')
tle = dsgp4.tle.TLE(tle)
print(tle)
TLE(
0 COSMOS 2251 DEB
1 34454U 93036SX  22068.91971155  .00000319  00000-0  11812-3 0  9996
2 34454  74.0583 280.7094 0037596 327.9100  31.9764 14.35844873683320
)

Now, as shown in the tle_propagation tutorial, we can propagate the TLE. However, instead of using the standard API, we require torch.autograd to record the operations w.r.t. the time.

Partials with respect to time#

Let’s compute the partials of the \(\partial \textrm{SGP4}\) output w.r.t. the propagation times

Single TLEs#

Let’s first see the case of single TLEs, propagated at various future times:

#let's take a random tensor of 10 tsince elements, where we track the gradients:
tsince=torch.rand((10,),requires_grad=True)
#the state is then:
state_teme = dsgp4.propagate(tle,
                tsinces=tsince,
                initialized=False)
#now, we can see that the gradient is tracked:
print(state_teme)
tensor([[[ 1.3919e+03, -6.9892e+03,  2.4119e+02],
         [ 1.9716e+00,  6.3285e-01,  7.1984e+00]],

        [[ 1.3954e+03, -6.9880e+03,  2.5419e+02],
         [ 1.9688e+00,  6.4673e-01,  7.1979e+00]],

        [[ 1.4238e+03, -6.9778e+03,  3.5857e+02],
         [ 1.9463e+00,  7.5825e-01,  7.1930e+00]],

        [[ 1.3352e+03, -7.0040e+03,  3.6308e+01],
         [ 2.0143e+00,  4.1367e-01,  7.2028e+00]],

        [[ 1.4175e+03, -6.9802e+03,  3.3537e+02],
         [ 1.9514e+00,  7.3347e-01,  7.1942e+00]],

        [[ 1.3961e+03, -6.9878e+03,  2.5670e+02],
         [ 1.9683e+00,  6.4942e-01,  7.1978e+00]],

        [[ 1.3845e+03, -6.9915e+03,  2.1416e+02],
         [ 1.9773e+00,  6.0394e-01,  7.1993e+00]],

        [[ 1.3531e+03, -7.0000e+03,  1.0063e+02],
         [ 2.0011e+00,  4.8252e-01,  7.2021e+00]],

        [[ 1.4309e+03, -6.9750e+03,  3.8471e+02],
         [ 1.9406e+00,  7.8616e-01,  7.1915e+00]],

        [[ 1.3827e+03, -6.9920e+03,  2.0788e+02],
         [ 1.9787e+00,  5.9724e-01,  7.1995e+00]]],
       grad_fn=<TransposeBackward0>)

Let’s now retrieve the partial derivatives of the SGP4 output w.r.t. time.

Since the state is position and velocity (i.e., \([x,y,z,v_x,v_y,v_z]\)), these partials will be all the elements of type:

(1)#\[\begin{equation} \dfrac{d \pmb{x}}{d t}=[\dfrac{dx}{dt}, \dfrac{dy}{dt}, \dfrac{dz}{dt}, \dfrac{d^2x}{dt^2}, \dfrac{d^2y}{dt^2}, \dfrac{d^2z}{dt^2}]^T=[v_x, v_y, v_z, \dfrac{dv_x}{dt}, \dfrac{dv_y}{dt}, \dfrac{dv_z}{dt}]^T \end{equation}\]

Note

One thing to be careful about is that \(\partial\textrm{SGP4}\), mirroring the original \(\textrm{SGP4}\), takes the time in minutes, and returns the state in km and km/s. Hence, the derivatives will have dimensions coherent to these, and to return to SI, conversions have to be made.

partial_derivatives = torch.zeros_like(state_teme)
for i in [0,1]:
    for j in [0,1,2]:
        tsince.grad=None
        state_teme[:,i,j].backward(torch.ones_like(tsince),retain_graph=True)
        partial_derivatives[:,i,j] = tsince.grad

#let's print to screen the partials:
print(partial_derivatives)
tensor([[[ 1.1830e+02,  3.7971e+01,  4.3191e+02],
         [-9.1937e-02,  4.6165e-01, -1.5973e-02]],

        [[ 1.1813e+02,  3.8804e+01,  4.3188e+02],
         [-9.2172e-02,  4.6157e-01, -1.6833e-02]],

        [[ 1.1678e+02,  4.5495e+01,  4.3158e+02],
         [-9.4042e-02,  4.6087e-01, -2.3745e-02]],

        [[ 1.2086e+02,  2.4820e+01,  4.3217e+02],
         [-8.8200e-02,  4.6268e-01, -2.4050e-03]],

        [[ 1.1708e+02,  4.4009e+01,  4.3166e+02],
         [-9.3628e-02,  4.6104e-01, -2.2209e-02]],

        [[ 1.1810e+02,  3.8966e+01,  4.3187e+02],
         [-9.2217e-02,  4.6156e-01, -1.7000e-02]],

        [[ 1.1864e+02,  3.6237e+01,  4.3196e+02],
         [-9.1449e-02,  4.6181e-01, -1.4183e-02]],

        [[ 1.2007e+02,  2.8951e+01,  4.3213e+02],
         [-8.9382e-02,  4.6241e-01, -6.6651e-03]],

        [[ 1.1644e+02,  4.7170e+01,  4.3149e+02],
         [-9.4507e-02,  4.6068e-01, -2.5475e-02]],

        [[ 1.1872e+02,  3.5835e+01,  4.3197e+02],
         [-9.1335e-02,  4.6185e-01, -1.3767e-02]]])

Batch TLEs#

Let’s now see how it works for batch TLEs. The API is basically identical:

#we load 6 TLEs:
inp_file="""0 PSLV DEB
1 35350U 01049QJ  22068.76869562  .00000911  00000-0  24939-3 0  9998
2 35350  98.6033  64.7516 0074531  99.8340 261.1278 14.48029442457561
0 PSLV DEB *
1 35351U 01049QK  22066.70636923  .00002156  00000-0  63479-3 0  9999
2 35351  98.8179  29.5651 0005211  45.5944 314.5671 14.44732274457505
0 SL-18 DEB
1 35354U 93014BD  22068.76520028  .00021929  00000-0  20751-2 0  9995
2 35354  75.7302 100.7819 0059525 350.7978   9.2117 14.92216400847487
0 SL-18 DEB
1 35359U 93014BJ  22068.55187275  .00025514  00000-0  24908-2 0  9992
2 35359  75.7369 156.1582 0054843  50.5279 310.0745 14.91164684775759
0 SL-18 DEB
1 35360U 93014BK  22068.44021735  .00019061  00000-0  20292-2 0  9992
2 35360  75.7343 127.2487 0071107  32.5913 327.9635 14.86997880798827
0 METEOR 2-17 DEB
1 35364U 88005Y   22067.81503681  .00001147  00000-0  84240-3 0  9995
2 35364  82.5500  92.4124 0018834 303.2489 178.0638 13.94853833332534"""
lines=inp_file.splitlines()
#let's create the TLE objects
tles=[]
for i in range(0,len(lines),3):
    data=[]
    data.append(lines[i])
    data.append(lines[i+1])
    data.append(lines[i+2])
    tles.append(dsgp4.tle.TLE(data))
#we also create 9 random times, tracking the gradients:
tsinces=torch.rand((6,),requires_grad=True)
#let's initialize the TLEs:
_,tle_batch=dsgp4.initialize_tle(tles)
#let's propagate the batch:
state_teme = dsgp4.propagate_batch(tle_batch,
                tsinces=tsinces)

Now, let’s retrieve the partial of each TLE, at each propagated time, and store them into a Nx2x3 matrix:

#let's retrieve the partials w.r.t. time:
partial_derivatives = torch.zeros_like(state_teme)
for i in [0,1]:
    for j in [0,1,2]:
        tsinces.grad=None
        state_teme[:,i,j].backward(torch.ones_like(tsinces),retain_graph=True)
        partial_derivatives[:,i,j] = tsinces.grad

#let's print to screen the partials:
print(partial_derivatives)
tensor([[[ 5.5717e+01, -3.9090e+01,  4.4358e+02],
         [-2.0253e-01, -4.2658e-01, -8.1456e-03]],

        [[ 2.9100e+01, -6.2583e+01,  4.4374e+02],
         [-4.1110e-01, -2.3229e-01, -5.1401e-03]],

        [[-1.0821e+02, -3.2632e+01,  4.4225e+02],
         [ 9.6357e-02, -4.8897e-01, -1.2560e-02]],

        [[-3.1063e+01, -1.0878e+02,  4.4107e+02],
         [ 4.5478e-01, -1.9711e-01, -1.3972e-02]],

        [[-7.3310e+01, -8.8854e+01,  4.4132e+02],
         [ 3.0533e-01, -3.9079e-01, -2.5690e-02]],

        [[ 4.7610e+01, -3.6498e+02, -2.4646e+02],
         [ 3.7419e-02,  2.5334e-01, -3.6812e-01]]])

Partials with respect to TLE parameters#

Let’s now tackle the case in which we are interested in the partials of the \(\partial\textrm{SGP4}\) output w.r.t. the TLE parameters.

Single TLEs#

We first tackle the case of single TLE, propagated at multiple times:

In this case, we want the Jacobian of the output state, w.r.t. the following TLE parameters \(\textrm{TLE}=[n,e,i,\Omega,\omega,M,B^*,\dot{n},\ddot{n}]\), where:

  • \(n\) is the mean motion (also known as no_kozai in the original implementation) [rad/minute];

  • \(e\) is the eccentricity [-];

  • \(i\) is the inclination [rad];

  • \(\Omega\) is the right ascension of the ascending node [rad];

  • \(\omega\) is the argument of perigee [rad];

  • \(M\) is the mean anomaly [rad];

  • \(B^*\) is the Bstar parameter [1/earth radii]

  • \(\dot{n}\) mean motion first derivative [radians/\(\textrm{minute}^2\)]

  • \(\ddot{n}\) mean motion second derivative [radians/\(\textrm{minute}^2\)]

(2)#\[\begin{equation} \dfrac{\partial \pmb{x}}{\partial \textrm{TLE}}= \begin{bmatrix} \frac{\partial x}{\partial B^*} & \frac{\partial x}{\partial \dot{n}} & \frac{\partial x}{\partial \ddot{n}} & \frac{\partial x}{\partial e} & \frac{\partial x}{\partial \omega} & \frac{\partial x}{\partial i} & \frac{\partial x}{\partial M} & \frac{\partial x}{\partial n} & \frac{\partial x}{\partial \Omega} \\ \\ \frac{\partial y}{\partial B^*} & \frac{\partial y}{\partial \dot{n}} & \frac{\partial y}{\partial \ddot{n}} & \frac{\partial y}{\partial e} & \frac{\partial y}{\partial \omega} & \frac{\partial y}{\partial i} & \frac{\partial y}{\partial M} & \frac{\partial y}{\partial n} & \frac{\partial y}{\partial \Omega} \\ \\ \frac{\partial z}{\partial B^*} & \frac{\partial z}{\partial \dot{n}} & \frac{\partial z}{\partial \ddot{n}} & \frac{\partial z}{\partial e} & \frac{\partial z}{\partial \omega} & \frac{\partial z}{\partial i} & \frac{\partial z}{\partial M} & \frac{\partial z}{\partial n} & \frac{\partial z}{\partial \Omega} \\ \\ \frac{\partial v_x}{\partial B^*} & \frac{\partial v_x}{\partial \dot{n}} & \frac{\partial v_x}{\partial \ddot{n}} & \frac{\partial v_x}{\partial e} & \frac{\partial v_x}{\partial \omega} & \frac{\partial v_x}{\partial i} & \frac{\partial v_x}{\partial M} & \frac{\partial v_x}{\partial n} & \frac{\partial v_x}{\partial \Omega} \\ \\ \frac{\partial v_y}{\partial B^*} & \frac{\partial v_y}{\partial \dot{n}} & \frac{\partial v_y}{\partial \ddot{n}} & \frac{\partial v_y}{\partial e} & \frac{\partial v_y}{\partial \omega} & \frac{\partial v_y}{\partial i} & \frac{\partial v_y}{\partial M} & \frac{\partial v_y}{\partial n} & \frac{\partial v_y}{\partial \Omega} \\ \\ \frac{\partial v_z}{\partial B^*} & \frac{\partial v_z}{\partial \dot{n}} & \frac{\partial v_z}{\partial \ddot{n}} & \frac{\partial v_z}{\partial e} & \frac{\partial v_z}{\partial \omega} & \frac{\partial v_z}{\partial i} & \frac{\partial v_z}{\partial M} & \frac{\partial v_z}{\partial n} & \frac{\partial v_z}{\partial \Omega} \\ \\ \frac{\partial \dot{n}}{\partial B^*} & \frac{\partial \dot{n}}{\partial \dot{n}} & \frac{\partial \dot{n}}{\partial \ddot{n}} & \frac{\partial \dot{n}}{\partial e} & \frac{\partial \dot{n}}{\partial \omega} & \frac{\partial \dot{n}}{\partial i} & \frac{\partial \dot{n}}{\partial M} & \frac{\partial \dot{n}}{\partial n} & \frac{\partial \dot{n}}{\partial \Omega} \\ \\ \frac{\partial \ddot{n}}{\partial B^*} & \frac{\partial \ddot{n}}{\partial \dot{n}} & \frac{\partial \ddot{n}}{\partial \ddot{n}} & \frac{\partial \ddot{n}}{\partial e} & \frac{\partial \ddot{n}}{\partial \omega} & \frac{\partial \ddot{n}}{\partial i} & \frac{\partial \ddot{n}}{\partial M} & \frac{\partial \ddot{n}}{\partial n} & \frac{\partial \ddot{n}}{\partial \Omega} \end{bmatrix} \end{equation}\]
#as always, first, we create a TLE object:
tle=[]
tle.append('0 COSMOS 2251 DEB')
tle.append('1 34454U 93036SX  22068.91971155  .00000319  00000-0  11812-3 0  9996')
tle.append('2 34454  74.0583 280.7094 0037596 327.9100  31.9764 14.35844873683320')
tle = dsgp4.tle.TLE(tle)
print(tle)
tle_elements=dsgp4.initialize_tle(tle,with_grad=True)
TLE(
0 COSMOS 2251 DEB
1 34454U 93036SX  22068.91971155  .00000319  00000-0  11812-3 0  9996
2 34454  74.0583 280.7094 0037596 327.9100  31.9764 14.35844873683320
)
#let's select 10 random times:
tsince=torch.rand((10,))
#and let's propagate:
state_teme=dsgp4.propagate(tle,tsince)
#now we can build the partial derivatives matrix, of shape Nx6x9 (N is the number of tsince elements, 6 is the number of elements in the state vector, and 9 is the number of elements in the TLE):
partial_derivatives = torch.zeros((len(tsince),6,9))
for k in range(len(tsince)):
    for i in range(6):
        tle_elements.grad=None
        state_teme[k].flatten()[i].backward(retain_graph=True)
        partial_derivatives[k,i,:] = tle_elements.grad
#let's print them to screen:
print(partial_derivatives)
tensor([[[-2.2113e-04,  0.0000e+00,  0.0000e+00,  9.7500e+02,  1.8451e+03,
          -3.8854e+02,  1.8596e+03, -1.3589e+04,  6.9739e+03],
         [-9.4176e-04,  0.0000e+00,  0.0000e+00,  6.5945e+03,  7.7486e+02,
          -7.6927e+01,  7.6435e+02,  7.4841e+04,  1.4337e+03],
         [-1.3717e-03,  0.0000e+00,  0.0000e+00,  7.6386e+03,  6.8464e+03,
           1.0860e+02,  6.8894e+03,  1.9490e+03,  0.0000e+00],
         [-1.7743e-06,  0.0000e+00,  0.0000e+00,  7.0204e-01, -1.5035e+00,
          -7.0622e+00, -1.5123e+00,  8.9239e+00, -7.9726e-01],
         [-1.2734e-06,  0.0000e+00,  0.0000e+00,  4.9281e+00,  7.3347e+00,
          -1.3382e+00,  7.3556e+00,  1.0889e+01,  1.9383e+00],
         [-6.9204e-06,  0.0000e+00,  0.0000e+00,  5.6239e+00, -4.0085e-01,
           2.0486e+00, -4.1777e-01,  3.7903e+01,  0.0000e+00]],

        [[-2.2166e-04,  0.0000e+00,  0.0000e+00,  9.7507e+02,  1.8449e+03,
          -3.8927e+02,  1.8594e+03, -1.3588e+04,  6.9738e+03],
         [-9.4362e-04,  0.0000e+00,  0.0000e+00,  6.5950e+03,  7.7561e+02,
          -7.7064e+01,  7.6511e+02,  7.4842e+04,  1.4339e+03],
         [-1.3747e-03,  0.0000e+00,  0.0000e+00,  7.6392e+03,  6.8464e+03,
           1.0881e+02,  6.8894e+03,  1.9529e+03,  0.0000e+00],
         [-1.7775e-06,  0.0000e+00,  0.0000e+00,  7.0153e-01, -1.5037e+00,
          -7.0621e+00, -1.5125e+00,  8.9202e+00, -7.9805e-01],
         [-1.2763e-06,  0.0000e+00,  0.0000e+00,  4.9293e+00,  7.3346e+00,
          -1.3382e+00,  7.3555e+00,  1.0906e+01,  1.9382e+00],
         [-6.9331e-06,  0.0000e+00,  0.0000e+00,  5.6230e+00, -4.0163e-01,
           2.0486e+00, -4.1855e-01,  3.7901e+01,  0.0000e+00]],

        [[-1.0232e-04,  0.0000e+00,  0.0000e+00,  9.5517e+02,  1.8831e+03,
          -2.0676e+02,  1.8978e+03, -1.3830e+04,  6.9918e+03],
         [-4.8951e-04,  0.0000e+00,  0.0000e+00,  6.4716e+03,  5.8593e+02,
          -4.2482e+01,  5.7488e+02,  7.4614e+04,  1.3833e+03],
         [-6.6978e-04,  0.0000e+00,  0.0000e+00,  7.4907e+03,  6.8543e+03,
           5.5868e+01,  6.8977e+03,  9.6954e+02,  0.0000e+00],
         [-9.6320e-07,  0.0000e+00,  0.0000e+00,  8.2816e-01, -1.4506e+00,
          -7.0706e+00, -1.4593e+00,  9.8092e+00, -5.9951e-01],
         [-6.0711e-07,  0.0000e+00,  0.0000e+00,  4.6233e+00,  7.3535e+00,
          -1.3396e+00,  7.3753e+00,  6.6917e+00,  1.9782e+00],
         [-3.7022e-06,  0.0000e+00,  0.0000e+00,  5.8600e+00, -2.0633e-01,
           2.0509e+00, -2.2208e-01,  3.8219e+01,  0.0000e+00]],

        [[-5.7190e-05,  0.0000e+00,  0.0000e+00,  9.4511e+02,  1.8998e+03,
          -1.2430e+02,  1.9147e+03, -1.3947e+04,  6.9983e+03],
         [-2.9109e-04,  0.0000e+00,  0.0000e+00,  6.4185e+03,  5.0015e+02,
          -2.6860e+01,  4.8884e+02,  7.4548e+04,  1.3602e+03],
         [-3.8577e-04,  0.0000e+00,  0.0000e+00,  7.4217e+03,  6.8561e+03,
           3.1950e+01,  6.8997e+03,  5.2341e+02,  0.0000e+00],
         [-5.8347e-07,  0.0000e+00,  0.0000e+00,  8.8455e-01, -1.4262e+00,
          -7.0728e+00, -1.4349e+00,  1.0193e+01, -5.0972e-01],
         [-3.4510e-07,  0.0000e+00,  0.0000e+00,  4.4807e+00,  7.3602e+00,
          -1.3400e+00,  7.3824e+00,  4.7823e+00,  1.9958e+00],
         [-2.2279e-06,  0.0000e+00,  0.0000e+00,  5.9614e+00, -1.1810e-01,
           2.0515e+00, -1.3330e-01,  3.8298e+01,  0.0000e+00]],

        [[-2.4484e-06,  0.0000e+00,  0.0000e+00,  9.2962e+02,  1.9233e+03,
          -6.4782e+00,  1.9383e+03, -1.4121e+04,  7.0057e+03],
         [-1.3783e-05,  0.0000e+00,  0.0000e+00,  6.3456e+03,  3.7748e+02,
          -4.5389e+00,  3.6580e+02,  7.4491e+04,  1.3267e+03],
         [-1.7377e-05,  0.0000e+00,  0.0000e+00,  7.3212e+03,  6.8571e+03,
          -2.2259e+00,  6.9009e+03, -1.1499e+02,  0.0000e+00],
         [-2.8331e-08,  0.0000e+00,  0.0000e+00,  9.6419e-01, -1.3911e+00,
          -7.0740e+00, -1.3996e+00,  1.0722e+01, -3.8130e-01],
         [-1.5208e-08,  0.0000e+00,  0.0000e+00,  4.2723e+00,  7.3679e+00,
          -1.3401e+00,  7.3907e+00,  2.0490e+00,  2.0205e+00],
         [-1.0717e-07,  0.0000e+00,  0.0000e+00,  6.1000e+00,  7.9765e-03,
           2.0517e+00, -6.4294e-03,  3.8340e+01,  0.0000e+00]],

        [[-2.0948e-04,  0.0000e+00,  0.0000e+00,  9.7336e+02,  1.8485e+03,
          -3.7234e+02,  1.8630e+03, -1.3610e+04,  6.9757e+03],
         [-9.0055e-04,  0.0000e+00,  0.0000e+00,  6.5832e+03,  7.5803e+02,
          -7.3856e+01,  7.4747e+02,  7.4816e+04,  1.4292e+03],
         [-1.3049e-03,  0.0000e+00,  0.0000e+00,  7.6257e+03,  6.8473e+03,
           1.0390e+02,  6.8904e+03,  1.8620e+03,  0.0000e+00],
         [-1.7035e-06,  0.0000e+00,  0.0000e+00,  7.1337e-01, -1.4988e+00,
          -7.0631e+00, -1.5076e+00,  9.0050e+00, -7.7964e-01],
         [-1.2091e-06,  0.0000e+00,  0.0000e+00,  4.9015e+00,  7.3366e+00,
          -1.3384e+00,  7.3576e+00,  1.0516e+01,  1.9419e+00],
         [-6.6354e-06,  0.0000e+00,  0.0000e+00,  5.6457e+00, -3.8351e-01,
           2.0488e+00, -4.0033e-01,  3.7939e+01,  0.0000e+00]],

        [[-1.9688e-04,  0.0000e+00,  0.0000e+00,  9.7153e+02,  1.8523e+03,
          -3.5449e+02,  1.8668e+03, -1.3633e+04,  6.9776e+03],
         [-8.5535e-04,  0.0000e+00,  0.0000e+00,  6.5709e+03,  7.3948e+02,
          -7.0473e+01,  7.2887e+02,  7.4790e+04,  1.4243e+03],
         [-1.2323e-03,  0.0000e+00,  0.0000e+00,  7.6113e+03,  6.8483e+03,
           9.8720e+01,  6.8914e+03,  1.7661e+03,  0.0000e+00],
         [-1.6251e-06,  0.0000e+00,  0.0000e+00,  7.2585e-01, -1.4936e+00,
          -7.0641e+00, -1.5025e+00,  9.0938e+00, -7.6023e-01],
         [-1.1394e-06,  0.0000e+00,  0.0000e+00,  4.8720e+00,  7.3387e+00,
          -1.3385e+00,  7.3597e+00,  1.0104e+01,  1.9459e+00],
         [-6.3209e-06,  0.0000e+00,  0.0000e+00,  5.6695e+00, -3.6440e-01,
           2.0491e+00, -3.8111e-01,  3.7977e+01,  0.0000e+00]],

        [[-9.2573e-05,  0.0000e+00,  0.0000e+00,  9.5315e+02,  1.8865e+03,
          -1.8978e+02,  1.9013e+03, -1.3854e+04,  6.9932e+03],
         [-4.4835e-04,  0.0000e+00,  0.0000e+00,  6.4605e+03,  5.6827e+02,
          -3.9266e+01,  5.5717e+02,  7.4599e+04,  1.3786e+03],
         [-6.0955e-04,  0.0000e+00,  0.0000e+00,  7.4766e+03,  6.8547e+03,
           5.0944e+01,  6.8982e+03,  8.7776e+02,  0.0000e+00],
         [-8.8563e-07,  0.0000e+00,  0.0000e+00,  8.3981e-01, -1.4456e+00,
          -7.0712e+00, -1.4543e+00,  9.8891e+00, -5.8103e-01],
         [-5.5110e-07,  0.0000e+00,  0.0000e+00,  4.5942e+00,  7.3550e+00,
          -1.3397e+00,  7.3769e+00,  6.2989e+00,  1.9819e+00],
         [-3.3994e-06,  0.0000e+00,  0.0000e+00,  5.8812e+00, -1.8816e-01,
           2.0510e+00, -2.0380e-01,  3.8238e+01,  0.0000e+00]],

        [[-1.4326e-05,  0.0000e+00,  0.0000e+00,  9.3340e+02,  1.9178e+03,
          -3.4295e+01,  1.9327e+03, -1.4079e+04,  7.0042e+03],
         [-7.8638e-05,  0.0000e+00,  0.0000e+00,  6.3625e+03,  4.0645e+02,
          -9.8085e+00,  3.9486e+02,  7.4500e+04,  1.3346e+03],
         [-1.0037e-04,  0.0000e+00,  0.0000e+00,  7.3451e+03,  6.8570e+03,
           5.8425e+00,  6.9008e+03,  3.5774e+01,  0.0000e+00],
         [-1.6071e-07,  0.0000e+00,  0.0000e+00,  9.4549e-01, -1.3994e+00,
          -7.0739e+00, -1.4080e+00,  1.0599e+01, -4.1163e-01],
         [-8.8325e-08,  0.0000e+00,  0.0000e+00,  4.3220e+00,  7.3663e+00,
          -1.3401e+00,  7.3889e+00,  2.6947e+00,  2.0147e+00],
         [-6.0928e-07,  0.0000e+00,  0.0000e+00,  6.0680e+00, -2.1788e-02,
           2.0517e+00, -3.6383e-02,  3.8338e+01,  0.0000e+00]],

        [[-1.0969e-05,  0.0000e+00,  0.0000e+00,  9.3236e+02,  1.9193e+03,
          -2.6586e+01,  1.9343e+03, -1.4091e+04,  7.0046e+03],
         [-6.0628e-05,  0.0000e+00,  0.0000e+00,  6.3578e+03,  3.9842e+02,
          -8.3480e+00,  3.8680e+02,  7.4497e+04,  1.3324e+03],
         [-7.7122e-05,  0.0000e+00,  0.0000e+00,  7.3385e+03,  6.8571e+03,
           3.6064e+00,  6.9009e+03, -6.0073e+00,  0.0000e+00],
         [-1.2410e-07,  0.0000e+00,  0.0000e+00,  9.5068e-01, -1.3971e+00,
          -7.0740e+00, -1.4056e+00,  1.0634e+01, -4.0323e-01],
         [-6.7765e-08,  0.0000e+00,  0.0000e+00,  4.3082e+00,  7.3667e+00,
          -1.3401e+00,  7.3894e+00,  2.5158e+00,  2.0163e+00],
         [-4.7021e-07,  0.0000e+00,  0.0000e+00,  6.0769e+00, -1.3539e-02,
           2.0517e+00, -2.8082e-02,  3.8339e+01,  0.0000e+00]]])

Batch TLEs:#

As for the time derivatives, the API stays practically identical:

#we load 6 TLEs:
inp_file="""0 PSLV DEB
1 35350U 01049QJ  22068.76869562  .00000911  00000-0  24939-3 0  9998
2 35350  98.6033  64.7516 0074531  99.8340 261.1278 14.48029442457561
0 PSLV DEB *
1 35351U 01049QK  22066.70636923  .00002156  00000-0  63479-3 0  9999
2 35351  98.8179  29.5651 0005211  45.5944 314.5671 14.44732274457505
0 SL-18 DEB
1 35354U 93014BD  22068.76520028  .00021929  00000-0  20751-2 0  9995
2 35354  75.7302 100.7819 0059525 350.7978   9.2117 14.92216400847487
0 SL-18 DEB
1 35359U 93014BJ  22068.55187275  .00025514  00000-0  24908-2 0  9992
2 35359  75.7369 156.1582 0054843  50.5279 310.0745 14.91164684775759
0 SL-18 DEB
1 35360U 93014BK  22068.44021735  .00019061  00000-0  20292-2 0  9992
2 35360  75.7343 127.2487 0071107  32.5913 327.9635 14.86997880798827
0 METEOR 2-17 DEB
1 35364U 88005Y   22067.81503681  .00001147  00000-0  84240-3 0  9995
2 35364  82.5500  92.4124 0018834 303.2489 178.0638 13.94853833332534"""
lines=inp_file.splitlines()
#let's create the TLE objects
tles=[]
for i in range(0,len(lines),3):
    data=[]
    data.append(lines[i])
    data.append(lines[i+1])
    data.append(lines[i+2])
    tles.append(dsgp4.tle.TLE(data))
#we also create 6 random times, tracking the gradients:
tsinces=torch.rand((6,))
#let's now initialize the TLEs, activating the gradient tracking for the TLE parameters:
tle_elements,tle_batch=dsgp4.initialize_tle(tles,with_grad=True)
#let's now propagate the batch of TLEs:
state_teme = dsgp4.propagate_batch(tle_batch,tsinces)

Finally, we can build the matrix that contains the partial of the SGP4 output w.r.t. the TLE parameters, for each TLE:

#now we can build the partial derivatives matrix, of shape Nx6x9 (N is the number of tsince elements, 6 is the number of elements in the state vector, and 9 is the number of elements in the TLE):
partial_derivatives = torch.zeros((len(tsinces),6,9))
for k in range(len(tsinces)):
    for i in range(6):
        tle_elements[k].grad=None
        state_teme[k].flatten()[i].backward(retain_graph=True)
        partial_derivatives[k,i,:] = tle_elements[k].grad
#let's print them to screen:
print(partial_derivatives)
tensor([[[-1.2178e-05,  0.0000e+00,  0.0000e+00, -1.3776e+03,  9.5683e+02,
           8.7639e+00,  9.3222e+02, -3.2040e+04, -6.4406e+03],
         [-6.0338e-05,  0.0000e+00,  0.0000e+00,  2.0040e+03, -4.7084e+02,
          -6.1694e+00, -5.1697e+02, -6.7903e+04,  3.0391e+03],
         [ 9.7244e-05,  0.0000e+00,  0.0000e+00, -1.3877e+04,  7.0429e+03,
           6.8563e-01,  7.0258e+03, -1.0100e+02,  0.0000e+00],
         [-4.1970e-08,  0.0000e+00,  0.0000e+00,  2.9910e+00, -3.2021e+00,
           6.6834e+00, -3.1910e+00,  5.1174e+00,  5.4348e-01],
         [-3.6635e-08,  0.0000e+00,  0.0000e+00,  6.7609e+00, -6.7668e+00,
          -3.1532e+00, -6.7626e+00, -2.9423e+00,  9.7975e-01],
         [-1.4717e-07,  0.0000e+00,  0.0000e+00, -1.1807e+00, -6.5192e-02,
          -1.1154e+00, -1.0777e-02,  3.9016e+01,  0.0000e+00]],

        [[-2.5691e-04,  0.0000e+00,  0.0000e+00, -4.9526e+03,  3.3106e+02,
           1.1118e+02,  3.2907e+02, -6.5441e+04, -3.4810e+03],
         [-2.7619e-04,  0.0000e+00,  0.0000e+00, -1.0465e+03, -1.0677e+03,
          -1.9988e+02, -1.0697e+03, -3.7310e+04,  6.2081e+03],
         [ 7.3120e-04,  0.0000e+00,  0.0000e+00, -9.8787e+03,  7.0348e+03,
          -3.3079e+01,  7.0400e+03,  1.0524e+03,  0.0000e+00],
         [-6.1533e-07,  0.0000e+00,  0.0000e+00,  4.7625e+00, -6.5325e+00,
           3.6442e+00, -6.5349e+00, -1.4774e+00,  1.1220e+00],
         [ 3.4540e-07,  0.0000e+00,  0.0000e+00,  1.7185e+00, -3.6623e+00,
          -6.4267e+00, -3.6641e+00, -7.7667e+00,  3.4480e-01],
         [-3.8853e-06,  0.0000e+00,  0.0000e+00,  5.5165e+00, -2.4371e-01,
          -1.1434e+00, -2.4114e-01,  3.8975e+01,  0.0000e+00]],

        [[-3.1632e-04,  0.0000e+00,  0.0000e+00,  7.2484e+02, -1.6619e+03,
           8.3384e+01, -1.6829e+03,  1.3195e+04, -6.8041e+03],
         [ 1.5967e-03,  0.0000e+00,  0.0000e+00, -6.8820e+03, -4.1278e+02,
           1.8972e+01, -4.1055e+02, -6.9682e+04, -1.3176e+03],
         [ 4.7428e-05,  0.0000e+00,  0.0000e+00,  2.2606e+03,  6.7178e+03,
           1.7863e+01,  6.7973e+03,  2.8940e+02,  0.0000e+00],
         [ 1.5634e-06,  0.0000e+00,  0.0000e+00, -1.5414e+00,  1.4460e+00,
           7.2386e+00,  1.4564e+00, -9.0472e+00,  4.4482e-01],
         [ 3.2935e-07,  0.0000e+00,  0.0000e+00, -1.7523e+00, -7.4769e+00,
           1.3806e+00, -7.5207e+00, -3.6313e+00, -1.8228e+00],
         [-6.2725e-06,  0.0000e+00,  0.0000e+00,  7.2472e+00, -8.5625e-02,
           1.8696e+00, -9.3743e-02,  3.7743e+01,  0.0000e+00]],

        [[-3.8078e-05,  0.0000e+00,  0.0000e+00,  5.1221e+03, -6.8279e+02,
          -9.4419e-01, -6.6066e+02,  6.5102e+04, -2.8087e+03],
         [-7.3104e-06,  0.0000e+00,  0.0000e+00,  6.2997e+02, -1.5721e+03,
           5.3314e+00, -1.5951e+03, -2.8735e+04, -6.3579e+03],
         [ 8.6792e-05,  0.0000e+00,  0.0000e+00, -1.0404e+04,  6.7376e+03,
          -2.6736e+00,  6.7851e+03, -1.2578e+02,  0.0000e+00],
         [ 6.6465e-08,  0.0000e+00,  0.0000e+00, -5.8329e+00,  6.9513e+00,
           2.9694e+00,  6.9729e+00, -3.6720e+00,  1.7266e+00],
         [ 3.1775e-08,  0.0000e+00,  0.0000e+00,  1.2691e+00, -3.0623e+00,
           6.7242e+00, -3.0804e+00, -8.8173e+00, -7.1504e-01],
         [-2.1966e-07,  0.0000e+00,  0.0000e+00,  4.7118e+00, -3.4923e-02,
           1.8640e+00, -3.9473e-03,  3.7692e+01,  0.0000e+00]],

        [[-1.4497e-03,  0.0000e+00,  0.0000e+00,  4.9795e+03, -1.2925e+03,
           8.3605e+01, -1.2925e+03,  4.3096e+04, -5.5118e+03],
         [ 1.0723e-03,  0.0000e+00,  0.0000e+00, -3.5365e+03, -1.1300e+03,
           6.7387e+01, -1.1645e+03, -5.6845e+04, -4.2251e+03],
         [ 1.9850e-03,  0.0000e+00,  0.0000e+00, -7.1660e+03,  6.7319e+03,
           2.3407e+01,  6.8138e+03,  4.0276e+02,  0.0000e+00],
         [ 2.0388e-06,  0.0000e+00,  0.0000e+00, -3.6300e+00,  4.6336e+00,
           5.8584e+00,  4.6568e+00, -6.0765e+00,  1.2571e+00],
         [ 2.5913e-07,  0.0000e+00,  0.0000e+00,  2.1090e+00, -6.0332e+00,
           4.4573e+00, -6.0749e+00, -7.8444e+00, -1.3950e+00],
         [-6.9909e-06,  0.0000e+00,  0.0000e+00,  6.3484e+00, -1.4425e-01,
           1.8671e+00, -1.1767e-01,  3.7826e+01,  0.0000e+00]],

        [[-7.4234e-06,  0.0000e+00,  0.0000e+00, -6.1633e+02,  7.7246e+02,
           6.0741e+03,  7.6955e+02,  7.2109e+03,  3.9945e+03],
         [ 3.2895e-05,  0.0000e+00,  0.0000e+00, -4.0735e+03, -6.1140e+03,
           2.5514e+02, -6.0910e+03,  4.1047e+04, -6.2742e+02],
         [ 4.3050e-05,  0.0000e+00,  0.0000e+00,  6.0164e+03, -3.9318e+03,
           7.9523e+02, -3.9169e+03, -6.8352e+04,  0.0000e+00],
         [-1.5551e-07,  0.0000e+00,  0.0000e+00, -7.7583e-01,  6.3487e-01,
          -3.9650e+00,  6.3366e-01,  4.5343e+00,  6.1749e+00],
         [ 1.2303e-06,  0.0000e+00,  0.0000e+00,  6.2065e+00,  4.0355e+00,
          -1.6573e-01,  4.0280e+00, -3.2051e+01,  7.7951e-01],
         [ 7.9069e-07,  0.0000e+00,  0.0000e+00,  3.9325e+00, -6.1534e+00,
          -5.1717e-01, -6.1418e+00, -2.4406e+01,  0.0000e+00]]])