TLEJacobiansMapper.java
/* Copyright 2002-2022 CS GROUP
* Licensed to CS GROUP (CS) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* CS licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.orekit.propagation.analytical.tle;
import org.hipparchus.analysis.differentiation.Gradient;
import org.orekit.orbits.FieldOrbit;
import org.orekit.propagation.FieldSpacecraftState;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.integration.AbstractJacobiansMapper;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.FieldAbsoluteDate;
import org.orekit.utils.FieldPVCoordinates;
import org.orekit.utils.ParameterDriver;
import org.orekit.utils.ParameterDriversList;
/** Mapper between two-dimensional Jacobian matrices and one-dimensional {@link
* SpacecraftState#getAdditionalState(String) additional state arrays}.
* <p>
* This class does not hold the states by itself. Instances of this class are guaranteed
* to be immutable.
* </p>
* @author Luc Maisonobe
* @author Bryan Cazabonne
* @author Thomas Paulet
* @since 11.0
* @see org.orekit.propagation.analytical.tle.TLEPartialDerivativesEquations
* @see org.orekit.propagation.analytical.tle.TLEPropagator
* @see SpacecraftState#getAdditionalState(String)
* @see org.orekit.propagation.AbstractPropagator
*/
public class TLEJacobiansMapper extends AbstractJacobiansMapper {
/** State dimension, fixed to 6. */
public static final int STATE_DIMENSION = 6;
/** Selected parameters for Jacobian computation. */
private final ParameterDriversList parameters;
/** TLE propagator. */
private final FieldTLEPropagator<Gradient> gPropagator;
/** Parameters. */
private final Gradient[] gParameters;
/** Placeholder for the derivatives of state. */
private double[] stateTransition;
/** Simple constructor.
* @param name name of the Jacobians
* @param parameters selected parameters for Jacobian computation
* @param propagator the propagator that will handle the orbit propagation
*/
public TLEJacobiansMapper(final String name,
final ParameterDriversList parameters,
final TLEPropagator propagator) {
super(name, parameters);
// Initialize fields
this.parameters = parameters;
this.stateTransition = null;
// Intialize "field" propagator
final TLEGradientConverter converter = new TLEGradientConverter(propagator);
final FieldSpacecraftState<Gradient> gState = converter.getState();
this.gParameters = converter.getParameters(gState);
this.gPropagator = converter.getPropagator(gState, gParameters);
}
/** {@inheritDoc} */
@Override
public void setInitialJacobians(final SpacecraftState state, final double[][] dY1dY0,
final double[][] dY1dP, final double[] p) {
// map the converted state Jacobian to one-dimensional array
int index = 0;
for (int i = 0; i < STATE_DIMENSION; ++i) {
for (int j = 0; j < STATE_DIMENSION; ++j) {
p[index++] = (i == j) ? 1.0 : 0.0;
}
}
if (parameters.getNbParams() != 0) {
// map the converted parameters Jacobian to one-dimensional array
for (int i = 0; i < STATE_DIMENSION; ++i) {
for (int j = 0; j < parameters.getNbParams(); ++j) {
p[index++] = dY1dP[i][j];
}
}
}
}
/** {@inheritDoc} */
@Override
public void getStateJacobian(final SpacecraftState state, final double[][] dYdY0) {
computeDerivatives(state);
for (int i = 0; i < STATE_DIMENSION; i++) {
final double[] row = dYdY0[i];
for (int j = 0; j < STATE_DIMENSION; j++) {
row[j] = stateTransition[i * STATE_DIMENSION + j];
}
}
}
/** {@inheritDoc} */
@Override
public void getParametersJacobian(final SpacecraftState state, final double[][] dYdP) {
if (parameters.getNbParams() != 0) {
computeDerivatives(state);
for (int i = 0; i < STATE_DIMENSION; i++) {
final double[] row = dYdP[i];
for (int j = 0; j < parameters.getNbParams(); j++) {
row[j] = stateTransition[STATE_DIMENSION * STATE_DIMENSION + (j + parameters.getNbParams() * i)];
}
}
}
}
/** {@inheritDoc}
* @deprecated as of 11.1, not used anymore
*/
@Deprecated
public void analyticalDerivatives(final SpacecraftState s) {
computeDerivatives(s);
}
/** Compute analytical derivatives.
* @param state current state
* @since 11.1
*/
private void computeDerivatives(final SpacecraftState state) {
// Initialize Jacobians to zero
final int dim = STATE_DIMENSION;
final int paramDim = parameters.getNbParams();
final double[][] stateGrad = new double[dim][dim];
final double[][] paramGrad = new double[dim][paramDim];
// Initialize matrix
if (stateTransition == null) {
stateTransition = state.getAdditionalState(getName());
}
// Compute Jacobian
final AbsoluteDate target = state.getDate();
final FieldAbsoluteDate<Gradient> init = gPropagator.getTLE().getDate();
final double dt = target.durationFrom(init.toAbsoluteDate());
final FieldOrbit<Gradient> gOrbit = gPropagator.propagateOrbit(init.shiftedBy(dt), gParameters);
final FieldPVCoordinates<Gradient> gPv = gOrbit.getPVCoordinates();
final double[] derivativesX = gPv.getPosition().getX().getGradient();
final double[] derivativesY = gPv.getPosition().getY().getGradient();
final double[] derivativesZ = gPv.getPosition().getZ().getGradient();
final double[] derivativesVx = gPv.getVelocity().getX().getGradient();
final double[] derivativesVy = gPv.getVelocity().getY().getGradient();
final double[] derivativesVz = gPv.getVelocity().getZ().getGradient();
// Update Jacobian with respect to state
addToRow(derivativesX, 0, stateGrad);
addToRow(derivativesY, 1, stateGrad);
addToRow(derivativesZ, 2, stateGrad);
addToRow(derivativesVx, 3, stateGrad);
addToRow(derivativesVy, 4, stateGrad);
addToRow(derivativesVz, 5, stateGrad);
int index = TLEGradientConverter.FREE_STATE_PARAMETERS;
int parameterIndex = 0;
for (ParameterDriver driver : parameters.getDrivers()) {
if (driver.isSelected()) {
paramGrad[0][parameterIndex] += derivativesX[index];
paramGrad[1][parameterIndex] += derivativesY[index];
paramGrad[2][parameterIndex] += derivativesZ[index];
paramGrad[3][parameterIndex] += derivativesVx[index];
paramGrad[4][parameterIndex] += derivativesVy[index];
paramGrad[5][parameterIndex] += derivativesVz[index];
++index;
}
++parameterIndex;
}
// State derivatives
for (int i = 0; i < dim; i++) {
for (int j = 0; j < dim; j++) {
stateTransition[j + dim * i] = stateGrad[i][j];
}
}
// Propagation parameters derivatives
final int columnTop = dim * dim;
for (int k = 0; k < paramDim; k++) {
for (int i = 0; i < dim; ++i) {
stateTransition[columnTop + (i + dim * k)] = paramGrad[i][k];
}
}
}
/** Fill Jacobians rows.
* @param derivatives derivatives of a component
* @param index component index (0 for X, 1 for Y, 2 for Z, 3 for Vx, 4 for Vy, 5 for Vz)
* @param grad Jacobian of mean elements rate with respect to mean elements
*/
private void addToRow(final double[] derivatives, final int index,
final double[][] grad) {
for (int i = 0; i < 6; i++) {
grad[index][i] += derivatives[i];
}
}
}