TLEJacobiansMapper.java

  1. /* Copyright 2002-2021 CS GROUP
  2.  * Licensed to CS GROUP (CS) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * CS licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *   http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.orekit.propagation.analytical.tle;

  18. import org.hipparchus.analysis.differentiation.Gradient;
  19. import org.orekit.orbits.FieldOrbit;
  20. import org.orekit.propagation.FieldSpacecraftState;
  21. import org.orekit.propagation.SpacecraftState;
  22. import org.orekit.propagation.integration.AbstractJacobiansMapper;
  23. import org.orekit.time.AbsoluteDate;
  24. import org.orekit.time.FieldAbsoluteDate;
  25. import org.orekit.utils.FieldPVCoordinates;
  26. import org.orekit.utils.ParameterDriver;
  27. import org.orekit.utils.ParameterDriversList;

  28. /** Mapper between two-dimensional Jacobian matrices and one-dimensional {@link
  29.  * SpacecraftState#getAdditionalState(String) additional state arrays}.
  30.  * <p>
  31.  * This class does not hold the states by itself. Instances of this class are guaranteed
  32.  * to be immutable.
  33.  * </p>
  34.  * @author Luc Maisonobe
  35.  * @author Bryan Cazabonne
  36.  * @author Thomas Paulet
  37.  * @since 11.0
  38.  * @see org.orekit.propagation.analytical.tle.TLEPartialDerivativesEquations
  39.  * @see org.orekit.propagation.analytical.tle.TLEPropagator
  40.  * @see SpacecraftState#getAdditionalState(String)
  41.  * @see org.orekit.propagation.AbstractPropagator
  42.  */
  43. public class TLEJacobiansMapper extends AbstractJacobiansMapper {

  44.     /** State dimension, fixed to 6. */
  45.     public static final int STATE_DIMENSION = 6;

  46.     /** Selected parameters for Jacobian computation. */
  47.     private final ParameterDriversList parameters;

  48.     /** TLE propagator. */
  49.     private final FieldTLEPropagator<Gradient> gPropagator;

  50.     /** Parameters. */
  51.     private final Gradient[] gParameters;

  52.     /** Placeholder for the derivatives of state. */
  53.     private double[] stateTransition;

  54.     /** Simple constructor.
  55.      * @param name name of the Jacobians
  56.      * @param parameters selected parameters for Jacobian computation
  57.      * @param propagator the propagator that will handle the orbit propagation
  58.      */
  59.     public TLEJacobiansMapper(final String name,
  60.                               final ParameterDriversList parameters,
  61.                               final TLEPropagator propagator) {
  62.         super(name, parameters);

  63.         // Initialize fields
  64.         this.parameters      = parameters;
  65.         this.stateTransition = null;

  66.         // Intialize "field" propagator
  67.         final TLEGradientConverter           converter   = new TLEGradientConverter(propagator);
  68.         final FieldSpacecraftState<Gradient> gState      = converter.getState();
  69.         this.gParameters = converter.getParameters(gState);
  70.         this.gPropagator = converter.getPropagator(gState, gParameters);
  71.     }

  72.     /** {@inheritDoc} */
  73.     @Override
  74.     public void setInitialJacobians(final SpacecraftState state, final double[][] dY1dY0,
  75.                                     final double[][] dY1dP, final double[] p) {

  76.         // map the converted state Jacobian to one-dimensional array
  77.         int index = 0;
  78.         for (int i = 0; i < STATE_DIMENSION; ++i) {
  79.             for (int j = 0; j < STATE_DIMENSION; ++j) {
  80.                 p[index++] = (i == j) ? 1.0 : 0.0;
  81.             }
  82.         }

  83.         if (parameters.getNbParams() != 0) {

  84.             // map the converted parameters Jacobian to one-dimensional array
  85.             for (int i = 0; i < STATE_DIMENSION; ++i) {
  86.                 for (int j = 0; j < parameters.getNbParams(); ++j) {
  87.                     p[index++] = dY1dP[i][j];
  88.                 }
  89.             }
  90.         }

  91.     }

  92.     /** {@inheritDoc} */
  93.     @Override
  94.     public void getStateJacobian(final SpacecraftState state, final double[][] dYdY0) {
  95.         for (int i = 0; i < STATE_DIMENSION; i++) {
  96.             final double[] row = dYdY0[i];
  97.             for (int j = 0; j < STATE_DIMENSION; j++) {
  98.                 row[j] = stateTransition[i * STATE_DIMENSION + j];
  99.             }
  100.         }
  101.     }


  102.     /** {@inheritDoc} */
  103.     @Override
  104.     public void getParametersJacobian(final SpacecraftState state, final double[][] dYdP) {

  105.         if (parameters.getNbParams() != 0) {

  106.             for (int i = 0; i < STATE_DIMENSION; i++) {
  107.                 final double[] row = dYdP[i];
  108.                 for (int j = 0; j < parameters.getNbParams(); j++) {
  109.                     row[j] = stateTransition[STATE_DIMENSION * STATE_DIMENSION + (j + parameters.getNbParams() * i)];
  110.                 }
  111.             }

  112.         }

  113.     }

  114.     /** {@inheritDoc} */
  115.     @Override
  116.     public void analyticalDerivatives(final SpacecraftState s) {

  117.         // Initialize Jacobians to zero
  118.         final int dim = STATE_DIMENSION;
  119.         final int paramDim = parameters.getNbParams();
  120.         final double[][] stateGrad = new double[dim][dim];
  121.         final double[][] paramGrad = new double[dim][paramDim];

  122.         // Initialize matrix
  123.         if (stateTransition == null) {
  124.             stateTransition = s.getAdditionalState(getName());
  125.         }

  126.         // Compute Jacobian
  127.         final AbsoluteDate target = s.getDate();
  128.         final FieldAbsoluteDate<Gradient> init = gPropagator.getTLE().getDate();
  129.         final double dt = target.durationFrom(init.toAbsoluteDate());
  130.         final FieldOrbit<Gradient> gOrbit = gPropagator.propagateOrbit(init.shiftedBy(dt), gParameters);
  131.         final FieldPVCoordinates<Gradient> gPv = gOrbit.getPVCoordinates();

  132.         final double[] derivativesX   = gPv.getPosition().getX().getGradient();
  133.         final double[] derivativesY   = gPv.getPosition().getY().getGradient();
  134.         final double[] derivativesZ   = gPv.getPosition().getZ().getGradient();
  135.         final double[] derivativesVx  = gPv.getVelocity().getX().getGradient();
  136.         final double[] derivativesVy  = gPv.getVelocity().getY().getGradient();
  137.         final double[] derivativesVz  = gPv.getVelocity().getZ().getGradient();

  138.         // Update Jacobian with respect to state
  139.         addToRow(derivativesX,  0, stateGrad);
  140.         addToRow(derivativesY,  1, stateGrad);
  141.         addToRow(derivativesZ,  2, stateGrad);
  142.         addToRow(derivativesVx, 3, stateGrad);
  143.         addToRow(derivativesVy, 4, stateGrad);
  144.         addToRow(derivativesVz, 5, stateGrad);

  145.         int index = TLEGradientConverter.FREE_STATE_PARAMETERS;
  146.         int parameterIndex = 0;
  147.         for (ParameterDriver driver : parameters.getDrivers()) {
  148.             if (driver.isSelected()) {
  149.                 paramGrad[0][parameterIndex] += derivativesX[index];
  150.                 paramGrad[1][parameterIndex] += derivativesY[index];
  151.                 paramGrad[2][parameterIndex] += derivativesZ[index];
  152.                 paramGrad[3][parameterIndex] += derivativesVx[index];
  153.                 paramGrad[4][parameterIndex] += derivativesVy[index];
  154.                 paramGrad[5][parameterIndex] += derivativesVz[index];
  155.                 ++index;
  156.             }
  157.             ++parameterIndex;
  158.         }

  159.         // State derivatives
  160.         for (int i = 0; i < dim; i++) {
  161.             for (int j = 0; j < dim; j++) {
  162.                 stateTransition[j + dim * i] = stateGrad[i][j];
  163.             }
  164.         }

  165.         // Propagation parameters derivatives
  166.         final int columnTop = dim * dim;
  167.         for (int k = 0; k < paramDim; k++) {
  168.             for (int i = 0; i < dim; ++i) {
  169.                 stateTransition[columnTop + (i + dim * k)] = paramGrad[i][k];
  170.             }
  171.         }

  172.     }

  173.     /** Fill Jacobians rows.
  174.      * @param derivatives derivatives of a component
  175.      * @param index component index (0 for X, 1 for Y, 2 for Z, 3 for Vx, 4 for Vy, 5 for Vz)
  176.      * @param grad Jacobian of mean elements rate with respect to mean elements
  177.      */
  178.     private void addToRow(final double[] derivatives, final int index,
  179.                           final double[][] grad) {
  180.         for (int i = 0; i < 6; i++) {
  181.             grad[index][i] += derivatives[i];
  182.         }
  183.     }

  184. }