TLEJacobiansMapper.java

  1. /* Copyright 2002-2022 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.         computeDerivatives(state);
  96.         for (int i = 0; i < STATE_DIMENSION; i++) {
  97.             final double[] row = dYdY0[i];
  98.             for (int j = 0; j < STATE_DIMENSION; j++) {
  99.                 row[j] = stateTransition[i * STATE_DIMENSION + j];
  100.             }
  101.         }
  102.     }


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

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

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

  114.         }

  115.     }

  116.     /** {@inheritDoc}
  117.      * @deprecated as of 11.1, not used anymore
  118.      */
  119.     @Deprecated
  120.     public void analyticalDerivatives(final SpacecraftState s) {
  121.         computeDerivatives(s);
  122.     }

  123.     /** Compute analytical derivatives.
  124.      * @param state current state
  125.      * @since 11.1
  126.      */
  127.     private void computeDerivatives(final SpacecraftState state) {

  128.         // Initialize Jacobians to zero
  129.         final int dim = STATE_DIMENSION;
  130.         final int paramDim = parameters.getNbParams();
  131.         final double[][] stateGrad = new double[dim][dim];
  132.         final double[][] paramGrad = new double[dim][paramDim];

  133.         // Initialize matrix
  134.         if (stateTransition == null) {
  135.             stateTransition = state.getAdditionalState(getName());
  136.         }

  137.         // Compute Jacobian
  138.         final AbsoluteDate target = state.getDate();
  139.         final FieldAbsoluteDate<Gradient> init = gPropagator.getTLE().getDate();
  140.         final double dt = target.durationFrom(init.toAbsoluteDate());
  141.         final FieldOrbit<Gradient> gOrbit = gPropagator.propagateOrbit(init.shiftedBy(dt), gParameters);
  142.         final FieldPVCoordinates<Gradient> gPv = gOrbit.getPVCoordinates();

  143.         final double[] derivativesX   = gPv.getPosition().getX().getGradient();
  144.         final double[] derivativesY   = gPv.getPosition().getY().getGradient();
  145.         final double[] derivativesZ   = gPv.getPosition().getZ().getGradient();
  146.         final double[] derivativesVx  = gPv.getVelocity().getX().getGradient();
  147.         final double[] derivativesVy  = gPv.getVelocity().getY().getGradient();
  148.         final double[] derivativesVz  = gPv.getVelocity().getZ().getGradient();

  149.         // Update Jacobian with respect to state
  150.         addToRow(derivativesX,  0, stateGrad);
  151.         addToRow(derivativesY,  1, stateGrad);
  152.         addToRow(derivativesZ,  2, stateGrad);
  153.         addToRow(derivativesVx, 3, stateGrad);
  154.         addToRow(derivativesVy, 4, stateGrad);
  155.         addToRow(derivativesVz, 5, stateGrad);

  156.         int index = TLEGradientConverter.FREE_STATE_PARAMETERS;
  157.         int parameterIndex = 0;
  158.         for (ParameterDriver driver : parameters.getDrivers()) {
  159.             if (driver.isSelected()) {
  160.                 paramGrad[0][parameterIndex] += derivativesX[index];
  161.                 paramGrad[1][parameterIndex] += derivativesY[index];
  162.                 paramGrad[2][parameterIndex] += derivativesZ[index];
  163.                 paramGrad[3][parameterIndex] += derivativesVx[index];
  164.                 paramGrad[4][parameterIndex] += derivativesVy[index];
  165.                 paramGrad[5][parameterIndex] += derivativesVz[index];
  166.                 ++index;
  167.             }
  168.             ++parameterIndex;
  169.         }

  170.         // State derivatives
  171.         for (int i = 0; i < dim; i++) {
  172.             for (int j = 0; j < dim; j++) {
  173.                 stateTransition[j + dim * i] = stateGrad[i][j];
  174.             }
  175.         }

  176.         // Propagation parameters derivatives
  177.         final int columnTop = dim * dim;
  178.         for (int k = 0; k < paramDim; k++) {
  179.             for (int i = 0; i < dim; ++i) {
  180.                 stateTransition[columnTop + (i + dim * k)] = paramGrad[i][k];
  181.             }
  182.         }

  183.     }

  184.     /** Fill Jacobians rows.
  185.      * @param derivatives derivatives of a component
  186.      * @param index component index (0 for X, 1 for Y, 2 for Z, 3 for Vx, 4 for Vy, 5 for Vz)
  187.      * @param grad Jacobian of mean elements rate with respect to mean elements
  188.      */
  189.     private void addToRow(final double[] derivatives, final int index,
  190.                           final double[][] grad) {
  191.         for (int i = 0; i < 6; i++) {
  192.             grad[index][i] += derivatives[i];
  193.         }
  194.     }

  195. }