AbstractCartesianAdjointEquationTerm.java

  1. /* Copyright 2022-2025 Romain Serra
  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.control.indirect.adjoint;

  18. import org.hipparchus.CalculusFieldElement;
  19. import org.hipparchus.analysis.differentiation.FieldGradient;
  20. import org.hipparchus.analysis.differentiation.FieldGradientField;
  21. import org.hipparchus.analysis.differentiation.Gradient;
  22. import org.hipparchus.analysis.differentiation.GradientField;
  23. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  24. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  25. import org.hipparchus.util.MathArrays;
  26. import org.orekit.frames.Frame;
  27. import org.orekit.time.AbsoluteDate;
  28. import org.orekit.time.FieldAbsoluteDate;

  29. /**
  30.  * Abstract class to define terms in the adjoint equations and Hamiltonian for Cartesian coordinates.
  31.  * @author Romain Serra
  32.  * @see CartesianAdjointDerivativesProvider
  33.  * @see FieldCartesianAdjointDerivativesProvider
  34.  * @since 12.2
  35.  */
  36. public abstract class AbstractCartesianAdjointEquationTerm implements CartesianAdjointEquationTerm {

  37.     /** Dimension of gradient. */
  38.     private static final int GRADIENT_DIMENSION = 6;

  39.     /** {@inheritDoc} */
  40.     @Override
  41.     public double[] getRatesContribution(final AbsoluteDate date, final double[] stateVariables,
  42.                                          final double[] adjointVariables, final Frame frame) {
  43.         final GradientField field = GradientField.getField(GRADIENT_DIMENSION);
  44.         final FieldAbsoluteDate<Gradient> fieldDate = new FieldAbsoluteDate<>(field, date);
  45.         final Gradient[] stateAsGradients = buildGradientCartesianVector(stateVariables);
  46.         final FieldVector3D<Gradient> acceleration = getFieldAcceleration(fieldDate, stateAsGradients, frame);
  47.         final double[] accelerationXgradient = acceleration.getX().getGradient();
  48.         final double[] accelerationYgradient = acceleration.getY().getGradient();
  49.         final double[] accelerationZgradient = acceleration.getZ().getGradient();
  50.         final double[] contribution = new double[adjointVariables.length];
  51.         for (int i = 0; i < 6; i++) {
  52.             contribution[i] = -(accelerationXgradient[i] * adjointVariables[3] + accelerationYgradient[i] * adjointVariables[4] + accelerationZgradient[i] * adjointVariables[5]);
  53.         }
  54.         return contribution;
  55.     }

  56.     /** {@inheritDoc} */
  57.     @Override
  58.     public double getHamiltonianContribution(final AbsoluteDate date, final double[] stateVariables,
  59.                                              final double[] adjointVariables, final Frame frame) {
  60.         final Vector3D acceleration = getAcceleration(date, stateVariables, frame);
  61.         return acceleration.getX() * adjointVariables[3] + acceleration.getY() * adjointVariables[4] + acceleration.getZ() * adjointVariables[5];
  62.     }

  63.     /**
  64.      * Compute the acceleration vector.
  65.      *
  66.      * @param date           date
  67.      * @param stateVariables state variables
  68.      * @param frame          propagation frame
  69.      * @return acceleration vector
  70.      */
  71.     protected abstract Vector3D getAcceleration(AbsoluteDate date, double[] stateVariables,
  72.                                                 Frame frame);

  73.     /** {@inheritDoc} */
  74.     @Override
  75.     public <T extends CalculusFieldElement<T>> T[] getFieldRatesContribution(final FieldAbsoluteDate<T> date,
  76.                                                                              final T[] stateVariables,
  77.                                                                              final T[] adjointVariables,
  78.                                                                              final Frame frame) {
  79.         final FieldGradientField<T> field = FieldGradientField.getField(date.getField(), GRADIENT_DIMENSION);
  80.         final FieldAbsoluteDate<FieldGradient<T>> fieldDate = new FieldAbsoluteDate<>(field, date.toAbsoluteDate());
  81.         final FieldGradient<T>[] gradients = buildFieldGradientCartesianVector(stateVariables);
  82.         final FieldVector3D<FieldGradient<T>> acceleration = getFieldAcceleration(fieldDate, gradients, frame);
  83.         final T[] contribution = MathArrays.buildArray(date.getField(), adjointVariables.length);
  84.         final T[] accelerationXgradient = acceleration.getX().getGradient();
  85.         final T[] accelerationYgradient = acceleration.getY().getGradient();
  86.         final T[] accelerationZgradient = acceleration.getZ().getGradient();
  87.         for (int i = 0; i < 6; i++) {
  88.             contribution[i] = (accelerationXgradient[i].multiply(adjointVariables[3])
  89.                     .add(accelerationYgradient[i].multiply(adjointVariables[4])).add(accelerationZgradient[i].multiply(adjointVariables[5]))).negate();
  90.         }
  91.         return contribution;
  92.     }

  93.     /** {@inheritDoc} */
  94.     @Override
  95.     public <T extends CalculusFieldElement<T>> T getFieldHamiltonianContribution(final FieldAbsoluteDate<T> date,
  96.                                                                                  final T[] stateVariables,
  97.                                                                                  final T[] adjointVariables,
  98.                                                                                  final Frame frame) {
  99.         final FieldVector3D<T> acceleration = getFieldAcceleration(date, stateVariables, frame);
  100.         return acceleration.dotProduct(new FieldVector3D<>(adjointVariables[3], adjointVariables[4], adjointVariables[5]));
  101.     }

  102.     /**
  103.      * Compute the acceleration vector.
  104.      *
  105.      * @param <T>            field type
  106.      * @param date           date
  107.      * @param stateVariables state variables
  108.      * @param frame          propagation frame
  109.      * @return acceleration vector
  110.      */
  111.     protected abstract <T extends CalculusFieldElement<T>> FieldVector3D<T> getFieldAcceleration(FieldAbsoluteDate<T> date,
  112.                                                                                                  T[] stateVariables,
  113.                                                                                                  Frame frame);

  114.     /**
  115.      * Build a Cartesian vector whose components are independent variables for automatic differentiation at order 1.
  116.      * @param stateVariables Cartesian variables
  117.      * @return vector of independent variables
  118.      */
  119.     protected static Gradient[] buildGradientCartesianVector(final double[] stateVariables) {
  120.         final GradientField field = GradientField.getField(GRADIENT_DIMENSION);
  121.         final Gradient[] gradients = MathArrays.buildArray(field, GRADIENT_DIMENSION);
  122.         gradients[0] = Gradient.variable(GRADIENT_DIMENSION, 0, stateVariables[0]);
  123.         gradients[1] = Gradient.variable(GRADIENT_DIMENSION, 1, stateVariables[1]);
  124.         gradients[2] = Gradient.variable(GRADIENT_DIMENSION, 2, stateVariables[2]);
  125.         gradients[3] = Gradient.variable(GRADIENT_DIMENSION, 3, stateVariables[3]);
  126.         gradients[4] = Gradient.variable(GRADIENT_DIMENSION, 4, stateVariables[4]);
  127.         gradients[5] = Gradient.variable(GRADIENT_DIMENSION, 5, stateVariables[5]);
  128.         return gradients;
  129.     }

  130.     /**
  131.      * Build a Cartesian vector whose components are independent variables for automatic differentiation at order 1.
  132.      * @param stateVariables Cartesian variables
  133.      * @param <T> field type
  134.      * @return vector of independent variables
  135.      */
  136.     protected static <T extends CalculusFieldElement<T>> FieldGradient<T>[] buildFieldGradientCartesianVector(final T[] stateVariables) {
  137.         final FieldGradientField<T> field = FieldGradientField.getField(stateVariables[0].getField(), GRADIENT_DIMENSION);
  138.         final FieldGradient<T>[] gradients = MathArrays.buildArray(field, GRADIENT_DIMENSION);
  139.         gradients[0] = FieldGradient.variable(GRADIENT_DIMENSION, 0, stateVariables[0]);
  140.         gradients[1] = FieldGradient.variable(GRADIENT_DIMENSION, 1, stateVariables[1]);
  141.         gradients[2] = FieldGradient.variable(GRADIENT_DIMENSION, 2, stateVariables[2]);
  142.         gradients[3] = FieldGradient.variable(GRADIENT_DIMENSION, 3, stateVariables[3]);
  143.         gradients[4] = FieldGradient.variable(GRADIENT_DIMENSION, 4, stateVariables[4]);
  144.         gradients[5] = FieldGradient.variable(GRADIENT_DIMENSION, 5, stateVariables[5]);
  145.         return gradients;
  146.     }
  147. }