DSSTJacobiansMapper.java

  1. /* Copyright 2002-2020 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.semianalytical.dsst;

  18. import java.util.ArrayList;
  19. import java.util.Arrays;
  20. import java.util.List;
  21. import java.util.Map;

  22. import org.hipparchus.analysis.differentiation.Gradient;
  23. import org.orekit.errors.OrekitInternalError;
  24. import org.orekit.propagation.FieldSpacecraftState;
  25. import org.orekit.propagation.PropagationType;
  26. import org.orekit.propagation.SpacecraftState;
  27. import org.orekit.propagation.integration.AbstractJacobiansMapper;
  28. import org.orekit.propagation.semianalytical.dsst.forces.DSSTForceModel;
  29. import org.orekit.propagation.semianalytical.dsst.forces.FieldShortPeriodTerms;
  30. import org.orekit.propagation.semianalytical.dsst.utilities.FieldAuxiliaryElements;
  31. import org.orekit.utils.ParameterDriver;
  32. import org.orekit.utils.ParameterDriversList;

  33. /** Mapper between two-dimensional Jacobian matrices and one-dimensional {@link
  34.  * SpacecraftState#getAdditionalState(String) additional state arrays}.
  35.  * <p>
  36.  * This class does not hold the states by itself. Instances of this class are guaranteed
  37.  * to be immutable.
  38.  * </p>
  39.  * @author Luc Maisonobe
  40.  * @author Bryan Cazabonne
  41.  * @see org.orekit.propagation.semianalytical.dsst.DSSTPartialDerivativesEquations
  42.  * @see org.orekit.propagation.semianalytical.dsst.DSSTPropagator
  43.  * @see SpacecraftState#getAdditionalState(String)
  44.  * @see org.orekit.propagation.AbstractPropagator
  45.  */
  46. public class DSSTJacobiansMapper extends AbstractJacobiansMapper {

  47.     /** State dimension, fixed to 6.
  48.      * @since 9.0
  49.      */
  50.     public static final int STATE_DIMENSION = 6;

  51.     /** Retrograde factor I.
  52.      *  <p>
  53.      *  DSST model needs equinoctial orbit as internal representation.
  54.      *  Classical equinoctial elements have discontinuities when inclination
  55.      *  is close to zero. In this representation, I = +1. <br>
  56.      *  To avoid this discontinuity, another representation exists and equinoctial
  57.      *  elements can be expressed in a different way, called "retrograde" orbit.
  58.      *  This implies I = -1. <br>
  59.      *  As Orekit doesn't implement the retrograde orbit, I is always set to +1.
  60.      *  But for the sake of consistency with the theory, the retrograde factor
  61.      *  has been kept in the formulas.
  62.      *  </p>
  63.      */
  64.     private static final int I = 1;

  65.     /** Name. */
  66.     private String name;

  67.     /** Selected parameters for Jacobian computation. */
  68.     private final ParameterDriversList parameters;

  69.     /** Parameters map. */
  70.     private Map<ParameterDriver, Integer> map;

  71.     /** Propagator computing state evolution. */
  72.     private final DSSTPropagator propagator;

  73.     /** Placeholder for the derivatives of the short period terms.*/
  74.     private double[] shortPeriodDerivatives;

  75.     /** Type of the orbit used for the propagation.*/
  76.     private PropagationType propagationType;

  77.     /** Simple constructor.
  78.      * @param name name of the Jacobians
  79.      * @param parameters selected parameters for Jacobian computation
  80.      * @param propagator the propagator that will handle the orbit propagation
  81.      * @param map parameters map
  82.      * @param propagationType type of the orbit used for the propagation (mean or osculating)
  83.      */
  84.     DSSTJacobiansMapper(final String name,
  85.                         final ParameterDriversList parameters,
  86.                         final DSSTPropagator propagator,
  87.                         final Map<ParameterDriver, Integer> map,
  88.                         final PropagationType propagationType) {

  89.         super(name, parameters);

  90.         shortPeriodDerivatives = null;

  91.         this.parameters      = parameters;
  92.         this.name            = name;
  93.         this.propagator      = propagator;
  94.         this.map             = map;
  95.         this.propagationType = propagationType;

  96.     }

  97.     /** {@inheritDoc} */
  98.     protected double[][] getConversionJacobian(final SpacecraftState state) {

  99.         final double[][] identity = new double[STATE_DIMENSION][STATE_DIMENSION];

  100.         for (int i = 0; i < STATE_DIMENSION; ++i) {
  101.             identity[i][i] = 1.0;
  102.         }

  103.         return identity;

  104.     }

  105.     /** {@inheritDoc} */
  106.     public void setInitialJacobians(final SpacecraftState state, final double[][] dY1dY0,
  107.                                     final double[][] dY1dP, final double[] p) {

  108.         // map the converted state Jacobian to one-dimensional array
  109.         int index = 0;
  110.         for (int i = 0; i < STATE_DIMENSION; ++i) {
  111.             for (int j = 0; j < STATE_DIMENSION; ++j) {
  112.                 p[index++] = (i == j) ? 1.0 : 0.0;
  113.             }
  114.         }

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

  116.             // map the converted parameters Jacobian to one-dimensional array
  117.             for (int i = 0; i < STATE_DIMENSION; ++i) {
  118.                 for (int j = 0; j < parameters.getNbParams(); ++j) {
  119.                     p[index++] = dY1dP[i][j];
  120.                 }
  121.             }
  122.         }

  123.     }

  124.     /** {@inheritDoc} */
  125.     public void getStateJacobian(final SpacecraftState state, final double[][] dYdY0) {

  126.         // extract additional state
  127.         final double[] p = state.getAdditionalState(name);

  128.         for (int i = 0; i < STATE_DIMENSION; i++) {
  129.             final double[] row = dYdY0[i];
  130.             for (int j = 0; j < STATE_DIMENSION; j++) {
  131.                 row[j] = p[i * STATE_DIMENSION + j] + shortPeriodDerivatives[i * STATE_DIMENSION + j];
  132.             }
  133.         }

  134.     }


  135.     /** {@inheritDoc} */
  136.     public void getParametersJacobian(final SpacecraftState state, final double[][] dYdP) {

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

  138.             // extract the additional state
  139.             final double[] p = state.getAdditionalState(name);

  140.             for (int i = 0; i < STATE_DIMENSION; i++) {
  141.                 final double[] row = dYdP[i];
  142.                 for (int j = 0; j < parameters.getNbParams(); j++) {
  143.                     row[j] = p[STATE_DIMENSION * STATE_DIMENSION + (j + parameters.getNbParams() * i)] +
  144.                              shortPeriodDerivatives[STATE_DIMENSION * STATE_DIMENSION + (j + parameters.getNbParams() * i)];
  145.                 }
  146.             }

  147.         }

  148.     }

  149.     /** {@inheritDoc} */
  150.     @Override
  151.     public int getAdditionalStateDimension() {
  152.         return STATE_DIMENSION * (STATE_DIMENSION + parameters.getNbParams());
  153.     }

  154.     /** Compute the derivatives of the short period terms related to the additional state parameters.
  155.     * @param s Current state information: date, kinematics, attitude, and additional state
  156.     */
  157.     @SuppressWarnings("unchecked")
  158.     public void setShortPeriodJacobians(final SpacecraftState s) {

  159.         final double[] p = s.getAdditionalState(name);
  160.         if (shortPeriodDerivatives == null) {
  161.             shortPeriodDerivatives = new double[p.length];
  162.         }

  163.         switch (propagationType) {
  164.             case MEAN :
  165.                 break;
  166.             case OSCULATING :
  167.                 // initialize Jacobians to zero
  168.                 final int paramDim = parameters.getNbParams();
  169.                 final int dim = 6;
  170.                 final double[][] dShortPerioddState = new double[dim][dim];
  171.                 final double[][] dShortPerioddParam = new double[dim][paramDim];
  172.                 final DSSTGradientConverter converter = new DSSTGradientConverter(s, propagator.getAttitudeProvider());

  173.                 // Compute Jacobian
  174.                 for (final DSSTForceModel forceModel : propagator.getAllForceModels()) {

  175.                     final FieldSpacecraftState<Gradient> dsState = converter.getState(forceModel);
  176.                     final Gradient[] dsParameters = converter.getParameters(dsState, forceModel);
  177.                     final FieldAuxiliaryElements<Gradient> auxiliaryElements = new FieldAuxiliaryElements<>(dsState.getOrbit(), I);

  178.                     final Gradient zero = dsState.getDate().getField().getZero();
  179.                     final List<FieldShortPeriodTerms<Gradient>> shortPeriodTerms = new ArrayList<>();
  180.                     shortPeriodTerms.addAll(forceModel.initialize(auxiliaryElements, propagationType, dsParameters));
  181.                     forceModel.updateShortPeriodTerms(dsParameters, dsState);
  182.                     final Gradient[] shortPeriod = new Gradient[6];
  183.                     Arrays.fill(shortPeriod, zero);
  184.                     for (final FieldShortPeriodTerms<Gradient> spt : shortPeriodTerms) {
  185.                         final Gradient[] spVariation = spt.value(dsState.getOrbit());
  186.                         for (int i = 0; i < spVariation .length; i++) {
  187.                             shortPeriod[i] = shortPeriod[i].add(spVariation[i]);
  188.                         }
  189.                     }

  190.                     final double[] derivativesASP  = shortPeriod[0].getGradient();
  191.                     final double[] derivativesExSP = shortPeriod[1].getGradient();
  192.                     final double[] derivativesEySP = shortPeriod[2].getGradient();
  193.                     final double[] derivativesHxSP = shortPeriod[3].getGradient();
  194.                     final double[] derivativesHySP = shortPeriod[4].getGradient();
  195.                     final double[] derivativesLSP  = shortPeriod[5].getGradient();

  196.                     // update Jacobian with respect to state
  197.                     addToRow(derivativesASP,  0, dShortPerioddState);
  198.                     addToRow(derivativesExSP, 1, dShortPerioddState);
  199.                     addToRow(derivativesEySP, 2, dShortPerioddState);
  200.                     addToRow(derivativesHxSP, 3, dShortPerioddState);
  201.                     addToRow(derivativesHySP, 4, dShortPerioddState);
  202.                     addToRow(derivativesLSP,  5, dShortPerioddState);

  203.                     int index = converter.getFreeStateParameters();
  204.                     for (ParameterDriver driver : forceModel.getParametersDrivers()) {
  205.                         if (driver.isSelected()) {
  206.                             final int parameterIndex = map.get(driver);
  207.                             dShortPerioddParam[0][parameterIndex] += derivativesASP[index];
  208.                             dShortPerioddParam[1][parameterIndex] += derivativesExSP[index];
  209.                             dShortPerioddParam[2][parameterIndex] += derivativesEySP[index];
  210.                             dShortPerioddParam[3][parameterIndex] += derivativesHxSP[index];
  211.                             dShortPerioddParam[4][parameterIndex] += derivativesHySP[index];
  212.                             dShortPerioddParam[5][parameterIndex] += derivativesLSP[index];
  213.                             ++index;
  214.                         }
  215.                     }
  216.                 }

  217.                 // Get orbital short period derivatives with respect orbital elements.
  218.                 for (int i = 0; i < dim; i++) {
  219.                     for (int j = 0; j < dim; j++) {
  220.                         shortPeriodDerivatives[j + dim * i] = dShortPerioddState[i][j];
  221.                     }
  222.                 }

  223.                 // Get orbital short period derivatives with respect to model parameters.
  224.                 final int columnTop = dim * dim;
  225.                 for (int k = 0; k < paramDim; k++) {
  226.                     for (int i = 0; i < dim; ++i) {
  227.                         shortPeriodDerivatives[columnTop + (i + dim * k)] = dShortPerioddParam[i][k];
  228.                     }
  229.                 }
  230.                 break;
  231.             default:
  232.                 throw new OrekitInternalError(null);
  233.         }
  234.     }

  235.     /** Fill Jacobians rows.
  236.      * @param derivatives derivatives of a component
  237.      * @param index component index (0 for a, 1 for ex, 2 for ey, 3 for hx, 4 for hy, 5 for l)
  238.      * @param dMeanElementRatedElement Jacobian of mean elements rate with respect to mean elements
  239.      */
  240.     private void addToRow(final double[] derivatives, final int index,
  241.                           final double[][] dMeanElementRatedElement) {

  242.         for (int i = 0; i < 6; i++) {
  243.             dMeanElementRatedElement[index][i] += derivatives[i];
  244.         }

  245.     }

  246. }