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.4099e+03, -6.9830e+03,  3.0732e+02],
         [ 1.9574e+00,  7.0351e-01,  7.1956e+00]],

        [[ 1.3858e+03, -6.9911e+03,  2.1903e+02],
         [ 1.9763e+00,  6.0916e-01,  7.1992e+00]],

        [[ 1.3796e+03, -6.9929e+03,  1.9659e+02],
         [ 1.9811e+00,  5.8516e-01,  7.1999e+00]],

        [[ 1.4191e+03, -6.9796e+03,  3.4107e+02],
         [ 1.9501e+00,  7.3956e-01,  7.1939e+00]],

        [[ 1.3681e+03, -6.9962e+03,  1.5490e+02],
         [ 1.9898e+00,  5.4058e-01,  7.2010e+00]],

        [[ 1.4362e+03, -6.9728e+03,  4.0455e+02],
         [ 1.9363e+00,  8.0734e-01,  7.1903e+00]],

        [[ 1.4227e+03, -6.9782e+03,  3.5456e+02],
         [ 1.9472e+00,  7.5396e-01,  7.1932e+00]],

        [[ 1.3261e+03, -7.0058e+03,  4.0446e+00],
         [ 2.0209e+00,  3.7912e-01,  7.2029e+00]],

        [[ 1.4171e+03, -6.9804e+03,  3.3356e+02],
         [ 1.9518e+00,  7.3154e-01,  7.1943e+00]],

        [[ 1.3495e+03, -7.0009e+03,  8.7635e+01],
         [ 2.0038e+00,  4.6861e-01,  7.2023e+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.1745e+02,  4.2211e+01,  4.3174e+02],
         [-9.3126e-02,  4.6123e-01, -2.0352e-02]],

        [[ 1.1858e+02,  3.6550e+01,  4.3195e+02],
         [-9.1537e-02,  4.6178e-01, -1.4506e-02]],

        [[ 1.1886e+02,  3.5110e+01,  4.3200e+02],
         [-9.1131e-02,  4.6191e-01, -1.3019e-02]],

        [[ 1.1701e+02,  4.4374e+01,  4.3164e+02],
         [-9.3730e-02,  4.6100e-01, -2.2586e-02]],

        [[ 1.1939e+02,  3.2435e+01,  4.3206e+02],
         [-9.0373e-02,  4.6214e-01, -1.0259e-02]],

        [[ 1.1618e+02,  4.8441e+01,  4.3142e+02],
         [-9.4859e-02,  4.6053e-01, -2.6789e-02]],

        [[ 1.1683e+02,  4.5238e+01,  4.3159e+02],
         [-9.3970e-02,  4.6090e-01, -2.3479e-02]],

        [[ 1.2125e+02,  2.2748e+01,  4.3217e+02],
         [-8.7605e-02,  4.6281e-01, -2.6820e-04]],

        [[ 1.1711e+02,  4.3893e+01,  4.3166e+02],
         [-9.3596e-02,  4.6105e-01, -2.2089e-02]],

        [[ 1.2023e+02,  2.8117e+01,  4.3214e+02],
         [-8.9144e-02,  4.6246e-01, -5.8043e-03]]])

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([[[ 4.9378e+01, -5.2357e+01,  4.4309e+02],
         [-2.0451e-01, -4.2536e-01, -2.3469e-02]],

        [[ 3.0530e+01, -6.1774e+01,  4.4376e+02],
         [-4.1098e-01, -2.3253e-01, -3.4300e-03]],

        [[-1.0960e+02, -2.5490e+01,  4.4238e+02],
         [ 9.4451e-02, -4.8948e-01, -4.7981e-03]],

        [[-2.9549e+01, -1.0943e+02,  4.4102e+02],
         [ 4.5492e-01, -1.9669e-01, -1.5723e-02]],

        [[-7.5259e+01, -8.6355e+01,  4.4148e+02],
         [ 3.0473e-01, -3.9142e-01, -2.2319e-02]],

        [[ 4.7723e+01, -3.6421e+02, -2.4758e+02],
         [ 3.7271e-02,  2.5447e-01, -3.6735e-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.0290e-04,  0.0000e+00,  0.0000e+00,  9.5529e+02,  1.8829e+03,
          -2.0776e+02,  1.8976e+03, -1.3829e+04,  6.9917e+03],
         [-4.9195e-04,  0.0000e+00,  0.0000e+00,  6.4722e+03,  5.8697e+02,
          -4.2673e+01,  5.7592e+02,  7.4615e+04,  1.3836e+03],
         [-6.7337e-04,  0.0000e+00,  0.0000e+00,  7.4916e+03,  6.8542e+03,
           5.6159e+01,  6.8976e+03,  9.7497e+02,  0.0000e+00],
         [-9.6779e-07,  0.0000e+00,  0.0000e+00,  8.2747e-01, -1.4509e+00,
          -7.0706e+00, -1.4596e+00,  9.8044e+00, -6.0060e-01],
         [-6.1046e-07,  0.0000e+00,  0.0000e+00,  4.6251e+00,  7.3534e+00,
          -1.3396e+00,  7.3752e+00,  6.7150e+00,  1.9780e+00],
         [-3.7201e-06,  0.0000e+00,  0.0000e+00,  5.8588e+00, -2.0740e-01,
           2.0509e+00, -2.2316e-01,  3.8218e+01,  0.0000e+00]],

        [[-4.2917e-05,  0.0000e+00,  0.0000e+00,  9.4150e+02,  1.9056e+03,
          -9.5860e+01,  1.9204e+03, -1.3988e+04,  7.0003e+03],
         [-2.2350e-04,  0.0000e+00,  0.0000e+00,  6.4006e+03,  4.7055e+02,
          -2.1472e+01,  4.5915e+02,  7.4530e+04,  1.3521e+03],
         [-2.9280e-04,  0.0000e+00,  0.0000e+00,  7.3977e+03,  6.8566e+03,
           2.3700e+01,  6.9002e+03,  3.6936e+02,  0.0000e+00],
         [-4.5080e-07,  0.0000e+00,  0.0000e+00,  9.0388e-01, -1.4178e+00,
          -7.0733e+00, -1.4264e+00,  1.0323e+01, -4.7873e-01],
         [-2.6064e-07,  0.0000e+00,  0.0000e+00,  4.4309e+00,  7.3623e+00,
          -1.3400e+00,  7.3846e+00,  4.1229e+00,  2.0018e+00],
         [-1.7174e-06,  0.0000e+00,  0.0000e+00,  5.9956e+00, -8.7662e-02,
           2.0516e+00, -1.0267e-01,  3.8316e+01,  0.0000e+00]],

        [[-9.7105e-05,  0.0000e+00,  0.0000e+00,  9.5410e+02,  1.8849e+03,
          -1.9773e+02,  1.8996e+03, -1.3843e+04,  6.9926e+03],
         [-4.6759e-04,  0.0000e+00,  0.0000e+00,  6.4657e+03,  5.7654e+02,
          -4.0772e+01,  5.6546e+02,  7.4606e+04,  1.3808e+03],
         [-6.3763e-04,  0.0000e+00,  0.0000e+00,  7.4832e+03,  6.8545e+03,
           5.3249e+01,  6.8979e+03,  9.2073e+02,  0.0000e+00],
         [-9.2198e-07,  0.0000e+00,  0.0000e+00,  8.3436e-01, -1.4479e+00,
          -7.0709e+00, -1.4566e+00,  9.8517e+00, -5.8968e-01],
         [-5.7718e-07,  0.0000e+00,  0.0000e+00,  4.6078e+00,  7.3543e+00,
          -1.3397e+00,  7.3761e+00,  6.4828e+00,  1.9802e+00],
         [-3.5412e-06,  0.0000e+00,  0.0000e+00,  5.8713e+00, -1.9667e-01,
           2.0510e+00, -2.1236e-01,  3.8230e+01,  0.0000e+00]],

        [[-1.8383e-04,  0.0000e+00,  0.0000e+00,  9.6956e+02,  1.8563e+03,
          -3.3561e+02,  1.8708e+03, -1.3657e+04,  6.9796e+03],
         [-8.0780e-04,  0.0000e+00,  0.0000e+00,  6.5579e+03,  7.1987e+02,
          -6.6895e+01,  7.0920e+02,  7.4764e+04,  1.4191e+03],
         [-1.1566e-03,  0.0000e+00,  0.0000e+00,  7.5961e+03,  6.8492e+03,
           9.3243e+01,  6.8924e+03,  1.6645e+03,  0.0000e+00],
         [-1.5418e-06,  0.0000e+00,  0.0000e+00,  7.3901e-01, -1.4882e+00,
          -7.0652e+00, -1.4970e+00,  9.1872e+00, -7.3970e-01],
         [-1.0669e-06,  0.0000e+00,  0.0000e+00,  4.8407e+00,  7.3408e+00,
          -1.3387e+00,  7.3619e+00,  9.6687e+00,  1.9501e+00],
         [-5.9879e-06,  0.0000e+00,  0.0000e+00,  5.6944e+00, -3.4420e-01,
           2.0494e+00, -3.6078e-01,  3.8015e+01,  0.0000e+00]],

        [[-9.7239e-05,  0.0000e+00,  0.0000e+00,  9.5413e+02,  1.8849e+03,
          -1.9796e+02,  1.8996e+03, -1.3843e+04,  6.9926e+03],
         [-4.6816e-04,  0.0000e+00,  0.0000e+00,  6.4658e+03,  5.7678e+02,
          -4.0816e+01,  5.6570e+02,  7.4606e+04,  1.3809e+03],
         [-6.3846e-04,  0.0000e+00,  0.0000e+00,  7.4834e+03,  6.8545e+03,
           5.3317e+01,  6.8979e+03,  9.2199e+02,  0.0000e+00],
         [-9.2304e-07,  0.0000e+00,  0.0000e+00,  8.3420e-01, -1.4480e+00,
          -7.0709e+00, -1.4567e+00,  9.8506e+00, -5.8993e-01],
         [-5.7795e-07,  0.0000e+00,  0.0000e+00,  4.6082e+00,  7.3543e+00,
          -1.3397e+00,  7.3761e+00,  6.4882e+00,  1.9801e+00],
         [-3.5453e-06,  0.0000e+00,  0.0000e+00,  5.8710e+00, -1.9692e-01,
           2.0510e+00, -2.1261e-01,  3.8229e+01,  0.0000e+00]],

        [[-4.1423e-05,  0.0000e+00,  0.0000e+00,  9.4110e+02,  1.9062e+03,
          -9.2804e+01,  1.9210e+03, -1.3993e+04,  7.0005e+03],
         [-2.1627e-04,  0.0000e+00,  0.0000e+00,  6.3987e+03,  4.6737e+02,
          -2.0893e+01,  4.5596e+02,  7.4528e+04,  1.3512e+03],
         [-2.8296e-04,  0.0000e+00,  0.0000e+00,  7.3951e+03,  6.8566e+03,
           2.2813e+01,  6.9003e+03,  3.5281e+02,  0.0000e+00],
         [-4.3649e-07,  0.0000e+00,  0.0000e+00,  9.0595e-01, -1.4169e+00,
          -7.0733e+00, -1.4255e+00,  1.0337e+01, -4.7540e-01],
         [-2.5174e-07,  0.0000e+00,  0.0000e+00,  4.4255e+00,  7.3625e+00,
          -1.3400e+00,  7.3849e+00,  4.0520e+00,  2.0025e+00],
         [-1.6625e-06,  0.0000e+00,  0.0000e+00,  5.9992e+00, -8.4392e-02,
           2.0516e+00, -9.9383e-02,  3.8317e+01,  0.0000e+00]],

        [[-2.0277e-04,  0.0000e+00,  0.0000e+00,  9.7239e+02,  1.8505e+03,
          -3.6288e+02,  1.8650e+03, -1.3622e+04,  6.9767e+03],
         [-8.7658e-04,  0.0000e+00,  0.0000e+00,  6.5767e+03,  7.4821e+02,
          -7.2064e+01,  7.3762e+02,  7.4802e+04,  1.4266e+03],
         [-1.2663e-03,  0.0000e+00,  0.0000e+00,  7.6181e+03,  6.8479e+03,
           1.0116e+02,  6.8909e+03,  1.8112e+03,  0.0000e+00],
         [-1.6620e-06,  0.0000e+00,  0.0000e+00,  7.1998e-01, -1.4961e+00,
          -7.0637e+00, -1.5049e+00,  9.0521e+00, -7.6936e-01],
         [-1.1721e-06,  0.0000e+00,  0.0000e+00,  4.8859e+00,  7.3377e+00,
          -1.3385e+00,  7.3587e+00,  1.0298e+01,  1.9440e+00],
         [-6.4689e-06,  0.0000e+00,  0.0000e+00,  5.6583e+00, -3.7339e-01,
           2.0490e+00, -3.9015e-01,  3.7959e+01,  0.0000e+00]],

        [[-1.2283e-04,  0.0000e+00,  0.0000e+00,  9.5918e+02,  1.8760e+03,
          -2.4125e+02,  1.8906e+03, -1.3783e+04,  6.9888e+03],
         [-5.7368e-04,  0.0000e+00,  0.0000e+00,  6.4943e+03,  6.2179e+02,
          -4.9017e+01,  6.1084e+02,  7.4649e+04,  1.3930e+03],
         [-7.9495e-04,  0.0000e+00,  0.0000e+00,  7.5192e+03,  6.8532e+03,
           6.5872e+01,  6.8965e+03,  1.1559e+03,  0.0000e+00],
         [-1.1199e-06,  0.0000e+00,  0.0000e+00,  8.0441e-01, -1.4607e+00,
          -7.0694e+00, -1.4694e+00,  9.6453e+00, -6.3705e-01],
         [-7.2421e-07,  0.0000e+00,  0.0000e+00,  4.6822e+00,  7.3503e+00,
          -1.3394e+00,  7.3720e+00,  7.4894e+00,  1.9708e+00],
         [-4.3162e-06,  0.0000e+00,  0.0000e+00,  5.8165e+00, -2.4323e-01,
           2.0506e+00, -2.5921e-01,  3.8174e+01,  0.0000e+00]],

        [[-2.1661e-04,  0.0000e+00,  0.0000e+00,  9.7437e+02,  1.8464e+03,
          -3.8230e+02,  1.8609e+03, -1.3597e+04,  6.9746e+03],
         [-9.2585e-04,  0.0000e+00,  0.0000e+00,  6.5902e+03,  7.6837e+02,
          -7.5743e+01,  7.5785e+02,  7.4831e+04,  1.4320e+03],
         [-1.3459e-03,  0.0000e+00,  0.0000e+00,  7.6336e+03,  6.8468e+03,
           1.0679e+02,  6.8898e+03,  1.9155e+03,  0.0000e+00],
         [-1.7470e-06,  0.0000e+00,  0.0000e+00,  7.0641e-01, -1.5017e+00,
          -7.0625e+00, -1.5105e+00,  8.9552e+00, -7.9047e-01],
         [-1.2485e-06,  0.0000e+00,  0.0000e+00,  4.9178e+00,  7.3355e+00,
          -1.3383e+00,  7.3563e+00,  1.0745e+01,  1.9397e+00],
         [-6.8106e-06,  0.0000e+00,  0.0000e+00,  5.6323e+00, -3.9416e-01,
           2.0487e+00, -4.1104e-01,  3.7917e+01,  0.0000e+00]],

        [[-1.9585e-04,  0.0000e+00,  0.0000e+00,  9.7138e+02,  1.8526e+03,
          -3.5301e+02,  1.8671e+03, -1.3635e+04,  6.9778e+03],
         [-8.5163e-04,  0.0000e+00,  0.0000e+00,  6.5699e+03,  7.3795e+02,
          -7.0194e+01,  7.2734e+02,  7.4788e+04,  1.4239e+03],
         [-1.2263e-03,  0.0000e+00,  0.0000e+00,  7.6102e+03,  6.8484e+03,
           9.8293e+01,  6.8914e+03,  1.7582e+03,  0.0000e+00],
         [-1.6186e-06,  0.0000e+00,  0.0000e+00,  7.2687e-01, -1.4932e+00,
          -7.0642e+00, -1.5020e+00,  9.1011e+00, -7.5863e-01],
         [-1.1337e-06,  0.0000e+00,  0.0000e+00,  4.8696e+00,  7.3388e+00,
          -1.3386e+00,  7.3599e+00,  1.0070e+01,  1.9462e+00],
         [-6.2950e-06,  0.0000e+00,  0.0000e+00,  5.6714e+00, -3.6283e-01,
           2.0491e+00, -3.7952e-01,  3.7980e+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([[[-4.9020e-04,  0.0000e+00,  0.0000e+00, -1.2224e+03,  7.9342e+02,
           3.4696e+02,  7.6931e+02, -3.1873e+04, -6.4040e+03],
         [-2.3272e-03,  0.0000e+00,  0.0000e+00,  2.3475e+03, -8.1264e+02,
          -1.6574e+02, -8.5869e+02, -6.8245e+04,  3.0844e+03],
         [ 3.6289e-03,  0.0000e+00,  0.0000e+00, -1.3917e+04,  7.0296e+03,
          -5.5760e+01,  7.0153e+03,  1.8675e+03,  0.0000e+00],
         [-1.6420e-06,  0.0000e+00,  0.0000e+00,  3.1372e+00, -3.2516e+00,
           6.6733e+00, -3.2429e+00,  1.4763e+00,  9.0310e-01],
         [-1.4123e-06,  0.0000e+00,  0.0000e+00,  6.7931e+00, -6.7319e+00,
          -3.1486e+00, -6.7330e+00, -1.0522e+01,  8.0830e-01],
         [-5.8180e-06,  0.0000e+00,  0.0000e+00, -3.9592e-01, -4.6026e-01,
          -1.1138e+00, -4.0520e-01,  3.8614e+01,  0.0000e+00]],

        [[-5.0940e-04,  0.0000e+00,  0.0000e+00, -4.8206e+03,  1.4454e+02,
           2.1509e+02,  1.4249e+02, -6.5542e+04, -3.4474e+03],
         [-5.2013e-04,  0.0000e+00,  0.0000e+00, -1.0005e+03, -1.1717e+03,
          -3.8313e+02, -1.1738e+03, -3.7564e+04,  6.2151e+03],
         [ 1.2962e-03,  0.0000e+00,  0.0000e+00, -9.7170e+03,  7.0247e+03,
          -6.5685e+01,  7.0300e+03,  2.1595e+03,  0.0000e+00],
         [-1.1084e-06,  0.0000e+00,  0.0000e+00,  4.4855e+00, -6.5405e+00,
           3.6389e+00, -6.5430e+00, -5.6289e+00,  1.2312e+00],
         [ 7.1698e-07,  0.0000e+00,  0.0000e+00,  1.5103e+00, -3.6273e+00,
          -6.4176e+00, -3.6291e+00, -1.0053e+01,  1.4889e-01],
         [-7.5295e-06,  0.0000e+00,  0.0000e+00,  5.8031e+00, -4.6603e-01,
          -1.1419e+00, -4.6364e-01,  3.8589e+01,  0.0000e+00]],

        [[-1.3342e-03,  0.0000e+00,  0.0000e+00,  6.6165e+02, -1.5976e+03,
           3.9582e+02, -1.6181e+03,  1.2836e+04, -6.7772e+03],
         [ 7.6721e-03,  0.0000e+00,  0.0000e+00, -6.9725e+03, -7.3516e+02,
           7.8571e+01, -7.3480e+02, -6.9994e+04, -1.3948e+03],
         [-4.8653e-04,  0.0000e+00,  0.0000e+00,  2.5706e+03,  6.7066e+03,
           9.8571e+01,  6.7856e+03,  1.9121e+03,  0.0000e+00],
         [ 7.2034e-06,  0.0000e+00,  0.0000e+00, -1.3694e+00,  1.5306e+00,
           7.2261e+00,  1.5418e+00, -7.5632e+00,  7.9648e-01],
         [ 2.8074e-06,  0.0000e+00,  0.0000e+00, -2.4345e+00, -7.4481e+00,
           1.3786e+00, -7.4908e+00, -1.0820e+01, -1.7526e+00],
         [-2.9849e-05,  0.0000e+00,  0.0000e+00,  7.0843e+00, -4.3421e-01,
           1.8666e+00, -4.4639e-01,  3.7297e+01,  0.0000e+00]],

        [[-1.1024e-03,  0.0000e+00,  0.0000e+00,  5.0430e+03, -5.8754e+02,
           3.9709e+01, -5.6511e+02,  6.5067e+04, -2.7848e+03],
         [-2.0733e-04,  0.0000e+00,  0.0000e+00,  6.4662e+02, -1.6138e+03,
           9.7394e+01, -1.6371e+03, -2.8862e+04, -6.3670e+03],
         [ 2.4974e-03,  0.0000e+00,  0.0000e+00, -1.0338e+04,  6.7364e+03,
           2.2848e+01,  6.7843e+03,  3.9016e+02,  0.0000e+00],
         [ 1.8910e-06,  0.0000e+00,  0.0000e+00, -5.7155e+00,  6.9620e+00,
           2.9690e+00,  6.9845e+00, -1.5475e+00,  1.7721e+00],
         [ 9.7589e-07,  0.0000e+00,  0.0000e+00,  1.1707e+00, -3.0365e+00,
           6.7235e+00, -3.0548e+00, -9.7481e+00, -6.1148e-01],
         [-6.5077e-06,  0.0000e+00,  0.0000e+00,  4.8794e+00, -1.4488e-01,
           1.8638e+00, -1.1469e-01,  3.7663e+01,  0.0000e+00]],

        [[-8.6886e-04,  0.0000e+00,  0.0000e+00,  5.0009e+03, -1.3195e+03,
           4.9386e+01, -1.3196e+03,  4.3133e+04, -5.5190e+03],
         [ 6.3914e-04,  0.0000e+00,  0.0000e+00, -3.5490e+03, -1.0948e+03,
           4.1352e+01, -1.1290e+03, -5.6802e+04, -4.2168e+03],
         [ 1.1979e-03,  0.0000e+00,  0.0000e+00, -7.2029e+03,  6.7326e+03,
           1.2500e+01,  6.8144e+03,  1.8176e+02,  0.0000e+00],
         [ 1.2279e-06,  0.0000e+00,  0.0000e+00, -3.6705e+00,  4.6244e+00,
           5.8589e+00,  4.6472e+00, -6.6819e+00,  1.2187e+00],
         [ 1.3361e-07,  0.0000e+00,  0.0000e+00,  2.1827e+00, -6.0408e+00,
           4.4576e+00, -6.0823e+00, -7.0567e+00, -1.4243e+00],
         [-4.1569e-06,  0.0000e+00,  0.0000e+00,  6.2998e+00, -9.7282e-02,
           1.8672e+00, -7.0124e-02,  3.7846e+01,  0.0000e+00]],

        [[-1.3604e-05,  0.0000e+00,  0.0000e+00, -6.2679e+02,  7.8085e+02,
           6.0208e+03,  7.7792e+02,  7.2725e+03,  4.0763e+03],
         [ 6.8271e-05,  0.0000e+00,  0.0000e+00, -3.9915e+03, -6.0597e+03,
           2.5291e+02, -6.0368e+03,  4.0629e+04, -6.1698e+02],
         [ 7.7289e-05,  0.0000e+00,  0.0000e+00,  6.0699e+03, -4.0133e+03,
           7.8828e+02, -3.9983e+03, -6.8689e+04,  0.0000e+00],
         [-2.3562e-07,  0.0000e+00,  0.0000e+00, -7.9275e-01,  6.2432e-01,
          -4.0474e+00,  6.2316e-01,  4.7137e+00,  6.1200e+00],
         [ 1.8402e-06,  0.0000e+00,  0.0000e+00,  6.0967e+00,  4.1185e+00,
          -1.6925e-01,  4.1107e+00, -3.0804e+01,  7.8798e-01],
         [ 1.2056e-06,  0.0000e+00,  0.0000e+00,  4.0975e+00, -6.0994e+00,
          -5.2787e-01, -6.0880e+00, -2.6185e+01,  0.0000e+00]]])