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.geometry.euclidean.threed.FieldVector3D;
21  import org.hipparchus.util.FastMath;
22  
23  /**
24   * Fuel cost penalized with a logarithmic term, which is a barrier so is not defined for epsilon equal to 0 or 1.
25   *
26   * @author Romain Serra
27   * @since 13.0
28   */
29  public class FieldLogarithmicBarrierCartesianFuel<T extends CalculusFieldElement<T>>
30          extends FieldPenalizedCartesianFuelCost<T> {
31  
32      /**
33       * Constructor.
34       *
35       * @param name                   adjoint name
36       * @param massFlowRateFactor     mass flow rate factor
37       * @param maximumThrustMagnitude maximum thrust magnitude
38       * @param epsilon                penalty weight
39       */
40      public FieldLogarithmicBarrierCartesianFuel(final String name, final T massFlowRateFactor,
41                                                  final T maximumThrustMagnitude, final T epsilon) {
42          super(name, massFlowRateFactor, maximumThrustMagnitude, epsilon);
43      }
44  
45      /** {@inheritDoc} */
46      @Override
47      public T evaluateFieldPenaltyFunction(final T controlNorm) {
48          return FastMath.log(controlNorm).add(FastMath.log(controlNorm.negate().add(1)));
49      }
50  
51      /** {@inheritDoc} */
52      @Override
53      public FieldVector3D<T> getFieldThrustAccelerationVector(final T[] adjointVariables, final T mass) {
54          final T thrustForceMagnitude = getThrustForceMagnitude(adjointVariables, mass);
55          return getFieldThrustDirection(adjointVariables).scalarMultiply(thrustForceMagnitude.divide(mass));
56      }
57  
58      /** {@inheritDoc} */
59      @Override
60      public void updateFieldAdjointDerivatives(final T[] adjointVariables, final T mass, final T[] adjointDerivatives) {
61          if (getAdjointDimension() > 6) {
62              adjointDerivatives[6] = adjointDerivatives[6].add(getFieldAdjointVelocityNorm(adjointVariables)
63                      .multiply(getThrustForceMagnitude(adjointVariables, mass)).divide(mass.square()));
64          }
65      }
66  
67      /**
68       * Computes the Euclidean norm of the thrust force.
69       * @param adjointVariables adjoint variables
70       * @param mass mass
71       * @return thrust force magnitude
72       */
73      private T getThrustForceMagnitude(final T[] adjointVariables, final T mass) {
74          final T twoEpsilon = getEpsilon().multiply(2);
75          T otherTerm = getFieldAdjointVelocityNorm(adjointVariables).divide(mass).subtract(1.);
76          if (getAdjointDimension() > 6) {
77              otherTerm = otherTerm.subtract(getMassFlowRateFactor().multiply(adjointVariables[6]));
78          }
79          return twoEpsilon.multiply(getMaximumThrustMagnitude())
80                  .divide(twoEpsilon.add(otherTerm).add(FastMath.sqrt(otherTerm.square().add(twoEpsilon.square()))));
81      }
82  
83      /** {@inheritDoc} */
84      @Override
85      public LogarithmicBarrierCartesianFuel toCartesianCost() {
86          return new LogarithmicBarrierCartesianFuel(getAdjointName(), getMassFlowRateFactor().getReal(),
87                  getMaximumThrustMagnitude().getReal(), getEpsilon().getReal());
88      }
89  }