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  
20  import org.hipparchus.CalculusFieldElement;
21  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
22  
23  /**
24   * Class for minimizing the flight duration (a.k.a. time of flight) with Cartesian coordinates.
25   * It is the integral over time of the constant one. The control is assumed to be bounded.
26   * It also assumes that no external acceleration depends on mass.
27   * If the mass flow rate factor is zero, then there is no adjoint for the mass.
28   *
29   * @author Romain Serra
30   * @see CartesianCost
31   * @see CartesianFlightDurationCost
32   * @since 13.0
33   */
34  public class FieldCartesianFlightDurationCost<T extends CalculusFieldElement<T>> extends FieldAbstractCartesianCost<T> {
35  
36      /**
37       * Maximum value of thrust force Euclidean norm.
38       */
39      private final T maximumThrustMagnitude;
40  
41      /**
42       * Constructor.
43       *
44       * @param name                   name
45       * @param massFlowRateFactor     mass flow rate factor
46       * @param maximumThrustMagnitude maximum thrust magnitude
47       */
48      public FieldCartesianFlightDurationCost(final String name, final T massFlowRateFactor, final T maximumThrustMagnitude) {
49          super(name, massFlowRateFactor);
50          this.maximumThrustMagnitude = maximumThrustMagnitude;
51      }
52  
53      /**
54       * Getter for maximum thrust magnitude.
55       *
56       * @return maximum thrust
57       */
58      public T getMaximumThrustMagnitude() {
59          return maximumThrustMagnitude;
60      }
61  
62      /**
63       * {@inheritDoc}
64       */
65      @Override
66      public FieldVector3D<T> getFieldThrustAccelerationVector(final T[] adjointVariables, final T mass) {
67          return new FieldVector3D<>(adjointVariables[3], adjointVariables[4], adjointVariables[5]).normalize()
68                  .scalarMultiply(maximumThrustMagnitude);
69      }
70  
71      /**
72       * {@inheritDoc}
73       */
74      @Override
75      public void updateFieldAdjointDerivatives(final T[] adjointVariables, final T mass, final T[] adjointDerivatives) {
76          if (getAdjointDimension() > 6) {
77              adjointDerivatives[6] =  adjointDerivatives[6].add(getFieldAdjointVelocityNorm(adjointVariables)
78                      .multiply(maximumThrustMagnitude).divide(mass.square()));
79          }
80      }
81  
82      /** {@inheritDoc} */
83      @Override
84      public T getFieldHamiltonianContribution(final T[] adjointVariables, final T mass) {
85          return mass.getField().getOne().newInstance(-1.);
86      }
87  
88      /** {@inheritDoc} */
89      @Override
90      public CartesianFlightDurationCost toCartesianCost() {
91          return new CartesianFlightDurationCost(getAdjointName(), getMassFlowRateFactor().getReal(),
92                  getMaximumThrustMagnitude().getReal());
93      }
94  }