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.cost;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.Field;
21  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
22  
23  /**
24   * Class for unbounded energy cost with Cartesian coordinates neglecting the mass consumption.
25   * Under this assumption, the mass is constant and there is no need to consider the corresponding adjoint variable.
26   * Here, the control vector is chosen as the acceleration given by thrusting, expressed in the propagation frame.
27   * This leads to the optimal thrust force being equal to the adjoint velocity vector times the mass.
28   *
29   * @param <T> field type
30   * @author Romain Serra
31   * @since 13.0
32   */
33  public class FieldUnboundedCartesianEnergyNeglectingMass<T extends CalculusFieldElement<T>> implements FieldCartesianCost<T> {
34  
35      /** Adjoint vector name. */
36      private final String name;
37  
38      /** Field. */
39      private final Field<T> field;
40  
41      /**
42       * Constructor.
43       * @param name name
44       * @param field field
45       */
46      public FieldUnboundedCartesianEnergyNeglectingMass(final String name, final Field<T> field) {
47          this.name = name;
48          this.field = field;
49      }
50  
51      /**
52       * Getter for adjoint vector name.
53       * @return name
54       */
55      @Override
56      public String getAdjointName() {
57          return name;
58      }
59  
60      /** {@inheritDoc} */
61      @Override
62      public int getAdjointDimension() {
63          return 6;
64      }
65  
66      /** {@inheritDoc} */
67      @Override
68      public T getMassFlowRateFactor() {
69          return field.getZero();
70      }
71  
72      /** {@inheritDoc} */
73      @Override
74      public FieldVector3D<T> getFieldThrustAccelerationVector(final T[] adjointVariables, final T mass) {
75          return new FieldVector3D<>(adjointVariables[3], adjointVariables[4], adjointVariables[5]);
76      }
77  
78      /** {@inheritDoc} */
79      @Override
80      public void updateFieldAdjointDerivatives(final T[] adjointVariables, final T mass, final T[] adjointDerivatives) {
81          // nothing to do
82      }
83  
84      /** {@inheritDoc} */
85      @Override
86      public T getFieldHamiltonianContribution(final T[] adjointVariables, final T mass) {
87          final FieldVector3D<T> thrustAcceleration = getFieldThrustAccelerationVector(adjointVariables, mass);
88          return thrustAcceleration.getNormSq().multiply(-1. / 2.);
89      }
90  
91      /** {@inheritDoc} */
92      @Override
93      public UnboundedCartesianEnergyNeglectingMass toCartesianCost() {
94          return new UnboundedCartesianEnergyNeglectingMass(getAdjointName());
95      }
96  }