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.3428e+03, -7.0024e+03,  6.3510e+01],
         [ 2.0087e+00,  4.4279e-01,  7.2026e+00]],

        [[ 1.3425e+03, -7.0025e+03,  6.2618e+01],
         [ 2.0089e+00,  4.4183e-01,  7.2026e+00]],

        [[ 1.3744e+03, -6.9945e+03,  1.7760e+02],
         [ 1.9850e+00,  5.6485e-01,  7.2004e+00]],

        [[ 1.4196e+03, -6.9794e+03,  3.4307e+02],
         [ 1.9497e+00,  7.4169e-01,  7.1938e+00]],

        [[ 1.4247e+03, -6.9775e+03,  3.6179e+02],
         [ 1.9456e+00,  7.6169e-01,  7.1928e+00]],

        [[ 1.3329e+03, -7.0045e+03,  2.8033e+01],
         [ 2.0160e+00,  4.0481e-01,  7.2028e+00]],

        [[ 1.3979e+03, -6.9872e+03,  2.6328e+02],
         [ 1.9669e+00,  6.5645e-01,  7.1975e+00]],

        [[ 1.4303e+03, -6.9753e+03,  3.8240e+02],
         [ 1.9411e+00,  7.8370e-01,  7.1916e+00]],

        [[ 1.3358e+03, -7.0039e+03,  3.8482e+01],
         [ 2.0139e+00,  4.1600e-01,  7.2027e+00]],

        [[ 1.4264e+03, -6.9768e+03,  3.6803e+02],
         [ 1.9443e+00,  7.6835e-01,  7.1925e+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.2053e+02,  2.6568e+01,  4.3215e+02],
         [-8.8701e-02,  4.6257e-01, -4.2065e-03]],

        [[ 1.2054e+02,  2.6510e+01,  4.3215e+02],
         [-8.8685e-02,  4.6257e-01, -4.1474e-03]],

        [[ 1.1910e+02,  3.3891e+01,  4.3203e+02],
         [-9.0786e-02,  4.6202e-01, -1.1762e-02]],

        [[ 1.1698e+02,  4.4502e+01,  4.3163e+02],
         [-9.3765e-02,  4.6098e-01, -2.2718e-02]],

        [[ 1.1674e+02,  4.5702e+01,  4.3157e+02],
         [-9.4099e-02,  4.6085e-01, -2.3958e-02]],

        [[ 1.2096e+02,  2.4289e+01,  4.3217e+02],
         [-8.8048e-02,  4.6272e-01, -1.8570e-03]],

        [[ 1.1801e+02,  3.9387e+01,  4.3185e+02],
         [-9.2335e-02,  4.6152e-01, -1.7435e-02]],

        [[ 1.1647e+02,  4.7022e+01,  4.3150e+02],
         [-9.4466e-02,  4.6070e-01, -2.5322e-02]],

        [[ 1.2083e+02,  2.4960e+01,  4.3217e+02],
         [-8.8241e-02,  4.6267e-01, -2.5490e-03]],

        [[ 1.1666e+02,  4.6102e+01,  4.3155e+02],
         [-9.4210e-02,  4.6080e-01, -2.4371e-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.2087e+01, -4.6708e+01,  4.4336e+02],
         [-2.0369e-01, -4.2594e-01, -1.6938e-02]],

        [[ 2.0800e+01, -6.7255e+01,  4.4354e+02],
         [-4.1169e-01, -2.3086e-01, -1.5060e-02]],

        [[-1.0761e+02, -3.5677e+01,  4.4216e+02],
         [ 9.7162e-02, -4.8871e-01, -1.5870e-02]],

        [[-1.7434e+01, -1.1462e+02,  4.4042e+02],
         [ 4.5586e-01, -1.9323e-01, -2.9717e-02]],

        [[-8.7815e+01, -7.0039e+01,  4.4195e+02],
         [ 3.0051e-01, -3.9504e-01, -4.1868e-04]],

        [[ 4.7116e+01, -3.6827e+02, -2.4161e+02],
         [ 3.8052e-02,  2.4842e-01, -3.7138e-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([[[-1.9182e-04,  0.0000e+00,  0.0000e+00,  9.7077e+02,  1.8538e+03,
          -3.4722e+02,  1.8684e+03, -1.3642e+04,  6.9784e+03],
         [-8.3701e-04,  0.0000e+00,  0.0000e+00,  6.5659e+03,  7.3193e+02,
          -6.9095e+01,  7.2130e+02,  7.4780e+04,  1.4223e+03],
         [-1.2030e-03,  0.0000e+00,  0.0000e+00,  7.6055e+03,  6.8487e+03,
           9.6612e+01,  6.8918e+03,  1.7270e+03,  0.0000e+00],
         [-1.5931e-06,  0.0000e+00,  0.0000e+00,  7.3092e-01, -1.4915e+00,
          -7.0645e+00, -1.5003e+00,  9.1298e+00, -7.5233e-01],
         [-1.1114e-06,  0.0000e+00,  0.0000e+00,  4.8600e+00,  7.3395e+00,
          -1.3386e+00,  7.3605e+00,  9.9365e+00,  1.9475e+00],
         [-6.1928e-06,  0.0000e+00,  0.0000e+00,  5.6791e+00, -3.5662e-01,
           2.0492e+00, -3.7328e-01,  3.7992e+01,  0.0000e+00]],

        [[-7.9182e-06,  0.0000e+00,  0.0000e+00,  9.3139e+02,  1.9207e+03,
          -1.9478e+01,  1.9357e+03, -1.4102e+04,  7.0050e+03],
         [-4.4047e-05,  0.0000e+00,  0.0000e+00,  6.3534e+03,  3.9102e+02,
          -7.0015e+00,  3.7938e+02,  7.4495e+04,  1.3304e+03],
         [-5.5855e-05,  0.0000e+00,  0.0000e+00,  7.3324e+03,  6.8571e+03,
           1.5447e+00,  6.9009e+03, -4.4532e+01,  0.0000e+00],
         [-9.0295e-08,  0.0000e+00,  0.0000e+00,  9.5546e-01, -1.3950e+00,
          -7.0740e+00, -1.4035e+00,  1.0665e+01, -3.9548e-01],
         [-4.9009e-08,  0.0000e+00,  0.0000e+00,  4.2955e+00,  7.3671e+00,
          -1.3401e+00,  7.3899e+00,  2.3508e+00,  2.0178e+00],
         [-3.4193e-07,  0.0000e+00,  0.0000e+00,  6.0851e+00, -5.9330e-03,
           2.0517e+00, -2.0428e-02,  3.8340e+01,  0.0000e+00]],

        [[-1.5783e-04,  0.0000e+00,  0.0000e+00,  9.6538e+02,  1.8644e+03,
          -2.9671e+02,  1.8790e+03, -1.3708e+04,  6.9836e+03],
         [-7.1060e-04,  0.0000e+00,  0.0000e+00,  6.5314e+03,  6.7945e+02,
          -5.9526e+01,  6.6867e+02,  7.4713e+04,  1.4084e+03],
         [-1.0041e-03,  0.0000e+00,  0.0000e+00,  7.5646e+03,  6.8510e+03,
           8.1962e+01,  6.8942e+03,  1.4551e+03,  0.0000e+00],
         [-1.3691e-06,  0.0000e+00,  0.0000e+00,  7.6604e-01, -1.4769e+00,
          -7.0671e+00, -1.4856e+00,  9.3778e+00, -6.9740e-01],
         [-9.2174e-07,  0.0000e+00,  0.0000e+00,  4.7758e+00,  7.3449e+00,
          -1.3390e+00,  7.3662e+00,  8.7711e+00,  1.9587e+00],
         [-5.3004e-06,  0.0000e+00,  0.0000e+00,  5.7453e+00, -3.0258e-01,
           2.0499e+00, -3.1892e-01,  3.8087e+01,  0.0000e+00]],

        [[-2.6336e-06,  0.0000e+00,  0.0000e+00,  9.2968e+02,  1.9232e+03,
          -6.9240e+00,  1.9382e+03, -1.4121e+04,  7.0057e+03],
         [-1.4820e-05,  0.0000e+00,  0.0000e+00,  6.3458e+03,  3.7795e+02,
          -4.6233e+00,  3.6626e+02,  7.4491e+04,  1.3268e+03],
         [-1.8688e-05,  0.0000e+00,  0.0000e+00,  7.3216e+03,  6.8571e+03,
          -2.0966e+00,  6.9009e+03, -1.1257e+02,  0.0000e+00],
         [-3.0459e-08,  0.0000e+00,  0.0000e+00,  9.6389e-01, -1.3912e+00,
          -7.0740e+00, -1.3997e+00,  1.0720e+01, -3.8179e-01],
         [-1.6356e-08,  0.0000e+00,  0.0000e+00,  4.2731e+00,  7.3679e+00,
          -1.3401e+00,  7.3907e+00,  2.0593e+00,  2.0204e+00],
         [-1.1523e-07,  0.0000e+00,  0.0000e+00,  6.0995e+00,  7.4995e-03,
           2.0517e+00, -6.9094e-03,  3.8340e+01,  0.0000e+00]],

        [[-1.0479e-04,  0.0000e+00,  0.0000e+00,  9.5567e+02,  1.8822e+03,
          -2.1101e+02,  1.8969e+03, -1.3825e+04,  6.9915e+03],
         [-4.9985e-04,  0.0000e+00,  0.0000e+00,  6.4744e+03,  5.9035e+02,
          -4.3288e+01,  5.7931e+02,  7.4618e+04,  1.3845e+03],
         [-6.8501e-04,  0.0000e+00,  0.0000e+00,  7.4942e+03,  6.8541e+03,
           5.7102e+01,  6.8975e+03,  9.9253e+02,  0.0000e+00],
         [-9.8259e-07,  0.0000e+00,  0.0000e+00,  8.2523e-01, -1.4518e+00,
          -7.0705e+00, -1.4605e+00,  9.7891e+00, -6.0414e-01],
         [-6.2131e-07,  0.0000e+00,  0.0000e+00,  4.6306e+00,  7.3531e+00,
          -1.3396e+00,  7.3749e+00,  6.7901e+00,  1.9773e+00],
         [-3.7780e-06,  0.0000e+00,  0.0000e+00,  5.8547e+00, -2.1088e-01,
           2.0509e+00, -2.2666e-01,  3.8214e+01,  0.0000e+00]],

        [[-4.4560e-05,  0.0000e+00,  0.0000e+00,  9.4193e+02,  1.9049e+03,
          -9.9204e+01,  1.9197e+03, -1.3983e+04,  7.0001e+03],
         [-2.3143e-04,  0.0000e+00,  0.0000e+00,  6.4027e+03,  4.7403e+02,
          -2.2105e+01,  4.6264e+02,  7.4532e+04,  1.3531e+03],
         [-3.0359e-04,  0.0000e+00,  0.0000e+00,  7.4005e+03,  6.8565e+03,
           2.4670e+01,  6.9002e+03,  3.8748e+02,  0.0000e+00],
         [-4.6644e-07,  0.0000e+00,  0.0000e+00,  9.0161e-01, -1.4188e+00,
          -7.0732e+00, -1.4274e+00,  1.0308e+01, -4.8237e-01],
         [-2.7041e-07,  0.0000e+00,  0.0000e+00,  4.4367e+00,  7.3620e+00,
          -1.3400e+00,  7.3844e+00,  4.2004e+00,  2.0011e+00],
         [-1.7775e-06,  0.0000e+00,  0.0000e+00,  5.9916e+00, -9.1240e-02,
           2.0516e+00, -1.0627e-01,  3.8314e+01,  0.0000e+00]],

        [[-1.2099e-04,  0.0000e+00,  0.0000e+00,  9.5883e+02,  1.8766e+03,
          -2.3821e+02,  1.8913e+03, -1.3787e+04,  6.9891e+03],
         [-5.6625e-04,  0.0000e+00,  0.0000e+00,  6.4923e+03,  6.1864e+02,
          -4.8442e+01,  6.0768e+02,  7.4646e+04,  1.3921e+03],
         [-7.8379e-04,  0.0000e+00,  0.0000e+00,  7.5167e+03,  6.8533e+03,
           6.4992e+01,  6.8966e+03,  1.1395e+03,  0.0000e+00],
         [-1.1061e-06,  0.0000e+00,  0.0000e+00,  8.0651e-01, -1.4598e+00,
          -7.0695e+00, -1.4685e+00,  9.6598e+00, -6.3375e-01],
         [-7.1374e-07,  0.0000e+00,  0.0000e+00,  4.6770e+00,  7.3506e+00,
          -1.3395e+00,  7.3723e+00,  7.4193e+00,  1.9714e+00],
         [-4.2623e-06,  0.0000e+00,  0.0000e+00,  5.8204e+00, -2.3999e-01,
           2.0506e+00, -2.5594e-01,  3.8178e+01,  0.0000e+00]],

        [[-6.9409e-05,  0.0000e+00,  0.0000e+00,  9.4803e+02,  1.8951e+03,
          -1.4766e+02,  1.9099e+03, -1.3914e+04,  6.9966e+03],
         [-3.4691e-04,  0.0000e+00,  0.0000e+00,  6.4334e+03,  5.2446e+02,
          -3.1286e+01,  5.1322e+02,  7.4564e+04,  1.3667e+03],
         [-4.6404e-04,  0.0000e+00,  0.0000e+00,  7.4414e+03,  6.8557e+03,
           3.8726e+01,  6.8993e+03,  6.4987e+02,  0.0000e+00],
         [-6.9179e-07,  0.0000e+00,  0.0000e+00,  8.6863e-01, -1.4331e+00,
          -7.0723e+00, -1.4418e+00,  1.0085e+01, -5.3516e-01],
         [-4.1674e-07,  0.0000e+00,  0.0000e+00,  4.5214e+00,  7.3584e+00,
          -1.3399e+00,  7.3805e+00,  5.3235e+00,  1.9909e+00],
         [-2.6464e-06,  0.0000e+00,  0.0000e+00,  5.9330e+00, -1.4309e-01,
           2.0513e+00, -1.5845e-01,  3.8280e+01,  0.0000e+00]],

        [[-2.2520e-04,  0.0000e+00,  0.0000e+00,  9.7556e+02,  1.8439e+03,
          -3.9413e+02,  1.8584e+03, -1.3582e+04,  6.9732e+03],
         [-9.5601e-04,  0.0000e+00,  0.0000e+00,  6.5984e+03,  7.8066e+02,
          -7.7985e+01,  7.7017e+02,  7.4849e+04,  1.4352e+03],
         [-1.3949e-03,  0.0000e+00,  0.0000e+00,  7.6430e+03,  6.8461e+03,
           1.1022e+02,  6.8891e+03,  1.9790e+03,  0.0000e+00],
         [-1.7987e-06,  0.0000e+00,  0.0000e+00,  6.9813e-01, -1.5051e+00,
          -7.0618e+00, -1.5139e+00,  8.8958e+00, -8.0333e-01],
         [-1.2958e-06,  0.0000e+00,  0.0000e+00,  4.9372e+00,  7.3341e+00,
          -1.3381e+00,  7.3549e+00,  1.1018e+01,  1.9371e+00],
         [-7.0185e-06,  0.0000e+00,  0.0000e+00,  5.6164e+00, -4.0683e-01,
           2.0485e+00, -4.2378e-01,  3.7890e+01,  0.0000e+00]],

        [[-1.5446e-04,  0.0000e+00,  0.0000e+00,  9.6482e+02,  1.8655e+03,
          -2.9155e+02,  1.8801e+03, -1.3715e+04,  6.9841e+03],
         [-6.9776e-04,  0.0000e+00,  0.0000e+00,  6.5279e+03,  6.7408e+02,
          -5.8547e+01,  6.6329e+02,  7.4706e+04,  1.4069e+03],
         [-9.8423e-04,  0.0000e+00,  0.0000e+00,  7.5604e+03,  6.8512e+03,
           8.0463e+01,  6.8945e+03,  1.4273e+03,  0.0000e+00],
         [-1.3460e-06,  0.0000e+00,  0.0000e+00,  7.6963e-01, -1.4754e+00,
          -7.0673e+00, -1.4841e+00,  9.4029e+00, -6.9178e-01],
         [-9.0286e-07,  0.0000e+00,  0.0000e+00,  4.7672e+00,  7.3454e+00,
          -1.3391e+00,  7.3668e+00,  8.6518e+00,  1.9598e+00],
         [-5.2089e-06,  0.0000e+00,  0.0000e+00,  5.7520e+00, -2.9706e-01,
           2.0500e+00, -3.1336e-01,  3.8096e+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([[[-2.8298e-04,  0.0000e+00,  0.0000e+00, -1.2882e+03,  8.6201e+02,
           2.0569e+02,  8.3770e+02, -3.1920e+04, -6.4215e+03],
         [-1.3682e-03,  0.0000e+00,  0.0000e+00,  2.2038e+03, -6.7002e+02,
          -9.9081e+01, -7.1606e+02, -6.8055e+04,  3.0665e+03],
         [ 2.1645e-03,  0.0000e+00,  0.0000e+00, -1.3905e+04,  7.0376e+03,
          -3.2181e+01,  7.0221e+03,  1.0474e+03,  0.0000e+00],
         [-9.6069e-07,  0.0000e+00,  0.0000e+00,  3.0803e+00, -3.2320e+00,
           6.6798e+00, -3.2223e+00,  3.0098e+00,  7.5301e-01],
         [-8.3281e-07,  0.0000e+00,  0.0000e+00,  6.7890e+00, -6.7489e+00,
          -3.1516e+00, -6.7477e+00, -7.3623e+00,  8.8029e-01],
         [-3.3853e-06,  0.0000e+00,  0.0000e+00, -7.2515e-01, -2.9518e-01,
          -1.1149e+00, -2.4032e-01,  3.8877e+01,  0.0000e+00]],

        [[-2.6467e-05,  0.0000e+00,  0.0000e+00, -5.0877e+03,  5.1122e+02,
           1.0546e+01,  5.0930e+02, -6.5455e+04, -3.5105e+03],
         [-2.9936e-05,  0.0000e+00,  0.0000e+00, -1.0966e+03, -9.6614e+02,
          -2.2407e+01, -9.6815e+02, -3.7126e+04,  6.1959e+03],
         [ 8.3615e-05,  0.0000e+00,  0.0000e+00, -1.0027e+04,  7.0386e+03,
          -1.5033e+00,  7.0437e+03, -2.6009e+01,  0.0000e+00],
         [-6.9317e-08,  0.0000e+00,  0.0000e+00,  5.0141e+00, -6.5191e+00,
           3.6462e+00, -6.5213e+00,  2.5306e+00,  1.0153e+00],
         [ 3.4039e-08,  0.0000e+00,  0.0000e+00,  1.9140e+00, -3.6931e+00,
          -6.4300e+00, -3.6948e+00, -5.5177e+00,  5.3404e-01],
         [-4.1042e-07,  0.0000e+00,  0.0000e+00,  5.2203e+00, -2.8433e-02,
          -1.1439e+00, -2.5702e-02,  3.9114e+01,  0.0000e+00]],

        [[-2.0259e-04,  0.0000e+00,  0.0000e+00,  7.3139e+02, -1.6679e+03,
           5.2936e+01, -1.6890e+03,  1.3234e+04, -6.8059e+03],
         [ 1.0106e-03,  0.0000e+00,  0.0000e+00, -6.8747e+03, -3.8133e+02,
           1.3165e+01, -3.7891e+02, -6.9668e+04, -1.3099e+03],
         [ 3.9220e-05,  0.0000e+00,  0.0000e+00,  2.2300e+03,  6.7181e+03,
           9.9977e+00,  6.7976e+03,  1.3062e+02,  0.0000e+00],
         [ 9.9298e-07,  0.0000e+00,  0.0000e+00, -1.5574e+00,  1.4376e+00,
           7.2390e+00,  1.4479e+00, -9.1841e+00,  4.1051e-01],
         [ 1.9250e-07,  0.0000e+00,  0.0000e+00, -1.6849e+00, -7.4788e+00,
           1.3807e+00, -7.5227e+00, -2.9285e+00, -1.8295e+00],
         [-3.9718e-06,  0.0000e+00,  0.0000e+00,  7.2596e+00, -5.1657e-02,
           1.8697e+00, -5.9375e-02,  3.7755e+01,  0.0000e+00]],

        [[-3.6068e-03,  0.0000e+00,  0.0000e+00,  4.8540e+03, -3.5059e+02,
           1.4055e+02, -3.2735e+02,  6.5104e+04, -2.7227e+03],
         [-6.3332e-04,  0.0000e+00,  0.0000e+00,  6.8205e+02, -1.7159e+03,
           3.2576e+02, -1.7398e+03, -2.9232e+04, -6.3834e+03],
         [ 8.0104e-03,  0.0000e+00,  0.0000e+00, -1.0166e+04,  6.7268e+03,
           8.6162e+01,  6.7757e+03,  1.6656e+03,  0.0000e+00],
         [ 5.8620e-06,  0.0000e+00,  0.0000e+00, -5.4019e+00,  6.9817e+00,
           2.9650e+00,  7.0064e+00,  3.7467e+00,  1.8834e+00],
         [ 3.6655e-06,  0.0000e+00,  0.0000e+00,  9.2200e-01, -2.9695e+00,
           6.7151e+00, -2.9882e+00, -1.1997e+01, -3.5380e-01],
         [-2.2475e-05,  0.0000e+00,  0.0000e+00,  5.2764e+00, -4.1773e-01,
           1.8616e+00, -3.8961e-01,  3.7335e+01,  0.0000e+00]],

        [[-1.9270e-03,  0.0000e+00,  0.0000e+00,  4.9620e+03, -1.2700e+03,
           1.1202e+02, -1.2699e+03,  4.3068e+04, -5.5056e+03],
         [ 1.4319e-03,  0.0000e+00,  0.0000e+00, -3.5264e+03, -1.1593e+03,
           8.9010e+01, -1.1939e+03, -5.6885e+04, -4.2318e+03],
         [ 2.6229e-03,  0.0000e+00,  0.0000e+00, -7.1350e+03,  6.7311e+03,
           3.2465e+01,  6.8132e+03,  5.8622e+02,  0.0000e+00],
         [ 2.6987e-06,  0.0000e+00,  0.0000e+00, -3.5958e+00,  4.6410e+00,
           5.8578e+00,  4.6645e+00, -5.5720e+00,  1.2890e+00],
         [ 3.8490e-07,  0.0000e+00,  0.0000e+00,  2.0475e+00, -6.0267e+00,
           4.4569e+00, -6.0685e+00, -8.4973e+00, -1.3705e+00],
         [-9.3530e-06,  0.0000e+00,  0.0000e+00,  6.3880e+00, -1.8326e-01,
           1.8670e+00, -1.5716e-01,  3.7801e+01,  0.0000e+00]],

        [[-1.3825e-05,  0.0000e+00,  0.0000e+00, -6.2712e+02,  7.8111e+02,
           6.0191e+03,  7.7818e+02,  7.2745e+03,  4.0789e+03],
         [ 6.9583e-05,  0.0000e+00,  0.0000e+00, -3.9889e+03, -6.0579e+03,
           2.5284e+02, -6.0351e+03,  4.0616e+04, -6.1665e+02],
         [ 7.8502e-05,  0.0000e+00,  0.0000e+00,  6.0716e+03, -4.0159e+03,
           7.8806e+02, -4.0009e+03, -6.8700e+04,  0.0000e+00],
         [-2.3815e-07,  0.0000e+00,  0.0000e+00, -7.9327e-01,  6.2399e-01,
          -4.0499e+00,  6.2282e-01,  4.7192e+00,  6.1182e+00],
         [ 1.8592e-06,  0.0000e+00,  0.0000e+00,  6.0932e+00,  4.1211e+00,
          -1.6936e-01,  4.1133e+00, -3.0764e+01,  7.8824e-01],
         [ 1.2188e-06,  0.0000e+00,  0.0000e+00,  4.1026e+00, -6.0977e+00,
          -5.2821e-01, -6.0863e+00, -2.6240e+01,  0.0000e+00]]])