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  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
21  import org.hipparchus.geometry.euclidean.threed.Vector3D;
22  import org.hipparchus.util.MathArrays;
23  import org.orekit.frames.Frame;
24  import org.orekit.time.AbsoluteDate;
25  import org.orekit.time.FieldAbsoluteDate;
26  import org.orekit.utils.ExtendedPositionProvider;
27  
28  /**
29   * Abstract class defining the contributions of a point-mass, single body gravity in the adjoint equations for Cartesian coordinates.
30   * @author Romain Serra
31   * @see CartesianAdjointEquationTerm
32   * @since 12.2
33   */
34  public abstract class AbstractCartesianAdjointNonCentralBodyTerm extends AbstractCartesianAdjointNewtonianTerm {
35  
36      /** Extended position provider for the body. */
37      private final ExtendedPositionProvider bodyPositionProvider;
38  
39      /**
40       * Constructor.
41       * @param mu body gravitational parameter.
42       * @param bodyPositionProvider body position provider
43       */
44      protected AbstractCartesianAdjointNonCentralBodyTerm(final double mu,
45                                                           final ExtendedPositionProvider bodyPositionProvider) {
46          super(mu);
47          this.bodyPositionProvider = bodyPositionProvider;
48      }
49  
50      /** {@inheritDoc} */
51      @Override
52      public double[] getPositionAdjointContribution(final AbsoluteDate date, final double[] stateVariables,
53                                                     final double[] adjointVariables, final Frame frame) {
54          return getNewtonianVelocityAdjointContribution(formRelativePosition(date, stateVariables, frame),
55              adjointVariables);
56      }
57  
58      /** {@inheritDoc} */
59      @Override
60      public <T extends CalculusFieldElement<T>> T[] getPositionAdjointFieldContribution(final FieldAbsoluteDate<T> date,
61                                                                                         final T[] stateVariables,
62                                                                                         final T[] adjointVariables,
63                                                                                         final Frame frame) {
64          return getFieldNewtonianVelocityAdjointContribution(formFieldRelativePosition(date, stateVariables, frame),
65              adjointVariables);
66      }
67  
68      /**
69       * Get body's position.
70       * @param date date
71       * @param frame frame
72       * @return position vector
73       */
74      protected Vector3D getBodyPosition(final AbsoluteDate date, final Frame frame) {
75          return bodyPositionProvider.getPosition(date, frame);
76      }
77  
78      /**
79       * Get body's position.
80       * @param <T> field type
81       * @param date date
82       * @param frame frame
83       * @return position vector
84       */
85      protected <T extends CalculusFieldElement<T>> FieldVector3D<T> getFieldBodyPosition(final FieldAbsoluteDate<T> date,
86                                                                                          final Frame frame) {
87          return bodyPositionProvider.getPosition(date, frame);
88      }
89  
90      /**
91       * Form relative position vector w.r.t. body.
92       * @param date date
93       * @param stateVariables Cartesian variables
94       * @param frame frame where Cartesian coordinates apply
95       * @return relative position vector as array
96       */
97      protected double[] formRelativePosition(final AbsoluteDate date, final double[] stateVariables, final Frame frame) {
98          final Vector3D bodyPosition = getBodyPosition(date, frame);
99          final double x = stateVariables[0] - bodyPosition.getX();
100         final double y = stateVariables[1] - bodyPosition.getY();
101         final double z = stateVariables[2] - bodyPosition.getZ();
102         return new double[] { x, y, z };
103     }
104 
105     /**
106      * Form relative position vector w.r.t. body.
107      * @param date date
108      * @param stateVariables Cartesian variables
109      * @param frame frame where Cartesian coordinates apply
110      * @param <T> field type
111      * @return relative position vector as array
112      */
113     protected <T extends CalculusFieldElement<T>> T[] formFieldRelativePosition(final FieldAbsoluteDate<T> date,
114                                                                               final T[] stateVariables,
115                                                                               final Frame frame) {
116         final FieldVector3D<T> bodyPosition = getFieldBodyPosition(date, frame);
117         final T x = stateVariables[0].subtract(bodyPosition.getX());
118         final T y = stateVariables[1].subtract(bodyPosition.getY());
119         final T z = stateVariables[2].subtract(bodyPosition.getZ());
120         final T[] relativePosition = MathArrays.buildArray(date.getField(), 3);
121         relativePosition[0] = x;
122         relativePosition[1] = y;
123         relativePosition[2] = z;
124         return relativePosition;
125     }
126 }