1   /* Copyright 2002-2021 CS GROUP
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.propagation.numerical.cr3bp;
18  
19  import java.util.Arrays;
20  
21  import org.hipparchus.analysis.differentiation.DerivativeStructure;
22  import org.hipparchus.linear.Array2DRowRealMatrix;
23  import org.hipparchus.linear.RealMatrix;
24  import org.orekit.bodies.CR3BPSystem;
25  import org.orekit.propagation.SpacecraftState;
26  import org.orekit.propagation.integration.AdditionalEquations;
27  
28  /** Class calculating the state transition matrix coefficient for CR3BP Computation.
29   * @see "Dynamical systems, the three-body problem, and space mission design, Koon, Lo, Marsden, Ross"
30   * @author Vincent Mouraux
31   * @since 10.2
32   */
33  public class STMEquations implements AdditionalEquations {
34  
35      /** Matrix Dimension. */
36      private static final int DIM = 6;
37  
38      /** Mass ratio of the considered CR3BP System. */
39      private final CR3BPSystem syst;
40  
41      /** Name of the equations. */
42      private final String name;
43  
44      /** Potential Hessian Matrix. */
45      private final double[][] jacobian = new double[DIM][DIM];
46  
47      /** Simple constructor.
48       * @param syst CR3BP System considered
49       */
50      public STMEquations(final CR3BPSystem syst) {
51          this.syst = syst;
52          this.name = "stmEquations";
53  
54          // Jacobian constant values initialization
55          for (int j = 0; j < jacobian.length; ++j) {
56              Arrays.fill(jacobian[j], 0.0);
57          }
58  
59          jacobian[0][3] = 1.0;
60          jacobian[1][4] = 1.0;
61          jacobian[2][5] = 1.0;
62          jacobian[3][4] = 2.0;
63          jacobian[4][3] = -2.0;
64      }
65  
66      /** Method adding the standard initial values of the additional state to the initial spacecraft state.
67       * @param s Initial state of the system
68       * @return s Initial augmented (with the additional equations) state
69       */
70      public SpacecraftState setInitialPhi(final SpacecraftState s) {
71          final int stateDimension = 36;
72          final double[] phi = new double[stateDimension];
73          for (int i = 0; i < stateDimension; ++i) {
74              phi[i] = 0.0;
75          }
76  
77          for (int i = 0; i < stateDimension; i = i + 7) {
78              phi[i] = 1.0;
79          }
80  
81          return s.addAdditionalState(name, phi);
82      }
83  
84      /** {@inheritDoc} */
85      public double[] computeDerivatives(final SpacecraftState s, final double[] dPhi) {
86  
87          // State Transition Matrix
88          final double[] phi = s.getAdditionalState(getName());
89  
90          // Spacecraft Potential
91          final DerivativeStructure potential = new CR3BPForceModel(syst).getPotential(s);
92  
93          // Potential derivatives
94          final double[] dU = potential.getAllDerivatives();
95  
96          // second order derivatives index
97          final int idXX = potential.getFactory().getCompiler().getPartialDerivativeIndex(2, 0, 0);
98          final int idXY = potential.getFactory().getCompiler().getPartialDerivativeIndex(1, 1, 0);
99          final int idXZ = potential.getFactory().getCompiler().getPartialDerivativeIndex(1, 0, 1);
100         final int idYY = potential.getFactory().getCompiler().getPartialDerivativeIndex(0, 2, 0);
101         final int idYZ = potential.getFactory().getCompiler().getPartialDerivativeIndex(0, 1, 1);
102         final int idZZ = potential.getFactory().getCompiler().getPartialDerivativeIndex(0, 0, 2);
103 
104         // New Jacobian values
105         jacobian[3][0] = dU[idXX];
106         jacobian[4][1] = dU[idYY];
107         jacobian[5][2] = dU[idZZ];
108         jacobian[3][1] = dU[idXY];
109         jacobian[4][0] = jacobian[3][1];
110         jacobian[3][2] = dU[idXZ];
111         jacobian[5][0] = jacobian[3][2];
112         jacobian[4][2] = dU[idYZ];
113         jacobian[5][1] = jacobian[4][2];
114 
115         // STM derivatives computation : dPhi = Jacobian * Phi if both dPhi and Phi are defined as Matrix
116         for (int k = 0; k < DIM; k++) {
117             for (int l = 0; l < DIM; l++) {
118                 for (int i = 0; i < DIM; i++) {
119                     dPhi[DIM * k + l] =
120                         dPhi[DIM * k + l] + jacobian[k][i] * phi[DIM * i + l];
121                 }
122             }
123         }
124 
125         // these equations have no effect on the main state itself
126         return null;
127     }
128 
129     /** {@inheritDoc} */
130     public String getName() {
131         return name;
132     }
133 
134     /** Method returning the State Transition Matrix.
135      * @param s SpacecraftState of the system
136      * @return phiM State Transition Matrix
137      */
138     public RealMatrix getStateTransitionMatrix(final SpacecraftState s) {
139         final double[][] phi2dA = new double[DIM][DIM];
140         final double[] stm = s.getAdditionalState(getName());
141         for (int i = 0; i < DIM; i++) {
142             for (int j = 0; j < 6; j++) {
143                 phi2dA[i][j] = stm[DIM * i + j];
144             }
145         }
146         return new Array2DRowRealMatrix(phi2dA, false);
147     }
148 }