1   /* Copyright 2022-2026 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   * @param <T> type of the field elements
30   * @author Romain Serra
31   * @see CartesianCost
32   * @see CartesianFlightDurationCost
33   * @since 13.0
34   */
35  public class FieldCartesianFlightDurationCost<T extends CalculusFieldElement<T>> extends FieldAbstractCartesianCost<T> {
36  
37      /**
38       * Maximum value of thrust force Euclidean norm.
39       */
40      private final T maximumThrustMagnitude;
41  
42      /**
43       * Constructor.
44       *
45       * @param name                   name
46       * @param massFlowRateFactor     mass flow rate factor
47       * @param maximumThrustMagnitude maximum thrust magnitude
48       */
49      public FieldCartesianFlightDurationCost(final String name, final T massFlowRateFactor, final T maximumThrustMagnitude) {
50          super(name, massFlowRateFactor);
51          this.maximumThrustMagnitude = maximumThrustMagnitude;
52      }
53  
54      /**
55       * Getter for maximum thrust magnitude.
56       *
57       * @return maximum thrust
58       */
59      public T getMaximumThrustMagnitude() {
60          return maximumThrustMagnitude;
61      }
62  
63      /**
64       * {@inheritDoc}
65       */
66      @Override
67      public FieldVector3D<T> getFieldThrustAccelerationVector(final T[] adjointVariables, final T mass) {
68          return new FieldVector3D<>(adjointVariables[3], adjointVariables[4], adjointVariables[5]).normalize()
69                  .scalarMultiply(maximumThrustMagnitude);
70      }
71  
72      /**
73       * {@inheritDoc}
74       */
75      @Override
76      public void updateFieldAdjointDerivatives(final T[] adjointVariables, final T mass, final T[] adjointDerivatives) {
77          if (getAdjointDimension() > 6) {
78              adjointDerivatives[6] =  adjointDerivatives[6].add(getFieldAdjointVelocityNorm(adjointVariables)
79                      .multiply(maximumThrustMagnitude).divide(mass.square()));
80          }
81      }
82  
83      /** {@inheritDoc} */
84      @Override
85      public T getFieldHamiltonianContribution(final T[] adjointVariables, final T mass) {
86          return mass.getField().getOne().newInstance(-1.);
87      }
88  
89      /** {@inheritDoc} */
90      @Override
91      public CartesianFlightDurationCost toCartesianCost() {
92          return new CartesianFlightDurationCost(getAdjointName(), getMassFlowRateFactor().getReal(),
93                  getMaximumThrustMagnitude().getReal());
94      }
95  }