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  import org.hipparchus.util.MathArrays;
23  import org.orekit.control.indirect.adjoint.CartesianAdjointDerivativesProvider;
24  import org.orekit.propagation.FieldSpacecraftState;
25  import org.orekit.propagation.events.FieldEventDetector;
26  import org.orekit.propagation.integration.FieldAdditionalDerivativesProvider;
27  import org.orekit.propagation.integration.FieldCombinedDerivatives;
28  
29  import java.util.stream.Stream;
30  
31  /**
32   * Interface to definite cost function in the frame of Pontryagin's Maximum Principle using Cartesian coordinates.
33   * It provides the link between the optimal control and the adjoint variables. This relationship is obtained by maximizing the Hamiltonian.
34   * The choice of control vector impacts on it.
35   * @author Romain Serra
36   * @see CartesianAdjointDerivativesProvider
37   * @since 13.0
38   */
39  public interface FieldCartesianCost<T extends CalculusFieldElement<T>> {
40  
41      /** Getter for adjoint vector name.
42       * @return adjoint vector name
43       */
44      String getAdjointName();
45  
46      /** Getter for adjoint vector dimension.
47       * @return adjoint dimension
48       */
49      int getAdjointDimension();
50  
51      /** Getter for mass flow rate factor. It is negated and multiplied by the thrust force magnitude to obtain the mass time derivative.
52       * The fact that it is a constant means that the exhaust speed is assumed to be independent of time.
53       * @return mass flow rate factor
54       */
55      T getMassFlowRateFactor();
56  
57      /**
58       * Computes the thrust acceleration vector in propagation frame from the adjoint variables and the mass.
59       * @param adjointVariables adjoint vector
60       * @param mass mass
61       * @return thrust vector
62       */
63      FieldVector3D<T> getFieldThrustAccelerationVector(T[] adjointVariables, T mass);
64  
65      /**
66       * Update the adjoint derivatives if necessary.
67       *
68       * @param adjointVariables   adjoint vector
69       * @param mass               mass
70       * @param adjointDerivatives derivatives to update
71       */
72      void updateFieldAdjointDerivatives(T[] adjointVariables, T mass, T[] adjointDerivatives);
73  
74      /**
75       * Computes the Hamiltonian contribution to the cost function.
76       * It equals the Lagrange-form integrand multiplied by -1.
77       * @param adjointVariables adjoint vector
78       * @param mass mass
79       * @return contribution to Hamiltonian
80       */
81      T getFieldHamiltonianContribution(T[] adjointVariables, T mass);
82  
83      /**
84       * Get the detectors needed for propagation.
85       * @param field field
86       * @return event detectors
87       */
88      default Stream<FieldEventDetector<T>> getFieldEventDetectors(final Field<T> field) {
89          return Stream.of();
90      }
91  
92      /**
93       * Get the derivatives provider to be able to integrate the cost function.
94       * @param name name of cost as additional state variable
95       * @return derivatives provider
96       * @since 13.0
97       */
98      default FieldAdditionalDerivativesProvider<T> getCostDerivativeProvider(final String name) {
99          return new FieldAdditionalDerivativesProvider<T>() {
100 
101             @Override
102             public String getName() {
103                 return name;
104             }
105 
106             @Override
107             public int getDimension() {
108                 return 1;
109             }
110 
111             @Override
112             public boolean yields(final FieldSpacecraftState<T> state) {
113                 return !state.hasAdditionalData(getAdjointName());
114             }
115 
116             @Override
117             public FieldCombinedDerivatives<T> combinedDerivatives(final FieldSpacecraftState<T> s) {
118                 final T mass = s.getMass();
119                 final T[] derivatives = MathArrays.buildArray(mass.getField(), 1);
120                 final T[] adjoint = s.getAdditionalState(getAdjointName());
121                 final T hamiltonianContribution = getFieldHamiltonianContribution(adjoint, s.getMass());
122                 derivatives[0] = hamiltonianContribution.negate();
123                 return new FieldCombinedDerivatives<>(derivatives, null);
124             }
125         };
126     }
127 
128     /**
129      * Method returning equivalent in non-Field.
130      * @return cost function for non-Field applications
131      */
132     CartesianCost toCartesianCost();
133 }