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.propagation.semianalytical.dsst.forces;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.Field;
21  import org.hipparchus.complex.Complex;
22  import org.hipparchus.complex.ComplexField;
23  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
24  import org.hipparchus.geometry.euclidean.threed.Vector3D;
25  import org.hipparchus.util.MathArrays;
26  import org.hipparchus.util.MathUtils;
27  import org.junit.jupiter.api.Assertions;
28  import org.junit.jupiter.api.DisplayName;
29  import org.junit.jupiter.api.Test;
30  import org.mockito.Mockito;
31  import org.orekit.attitudes.FrameAlignedProvider;
32  import org.orekit.forces.ForceModel;
33  import org.orekit.frames.FramesFactory;
34  import org.orekit.orbits.EquinoctialOrbit;
35  import org.orekit.orbits.FieldEquinoctialOrbit;
36  import org.orekit.orbits.FieldOrbit;
37  import org.orekit.orbits.PositionAngleType;
38  import org.orekit.propagation.FieldSpacecraftState;
39  import org.orekit.propagation.SpacecraftState;
40  import org.orekit.propagation.semianalytical.dsst.utilities.AuxiliaryElements;
41  import org.orekit.propagation.semianalytical.dsst.utilities.FieldAuxiliaryElements;
42  import org.orekit.time.AbsoluteDate;
43  import org.orekit.utils.Constants;
44  import org.orekit.utils.ParameterDriver;
45  
46  import java.util.Collections;
47  import java.util.List;
48  
49  class AbstractGaussianContributionTest {
50  
51      @Test
52      @DisplayName("Coverage test for attitude building when not depending on rate")
53      void testGetMeanElementRateWhenNotDependingOnAttitudeRate() {
54          testTemplateGetMeanElementRate(false);
55      }
56  
57      @Test
58      @DisplayName("Coverage test for attitude building when depending on rate")
59      void testGetMeanElementRateWhenDependingOnAttitudeRate() {
60          testTemplateGetMeanElementRate(true);
61      }
62  
63      void testTemplateGetMeanElementRate(final boolean dependsOnAttitudeRate) {
64          // GIVEN
65          final double mu = Constants.EIGEN5C_EARTH_MU;
66          final EquinoctialOrbit orbit = new EquinoctialOrbit(7e6, 0., 0.001, 0.01, 0., 0., PositionAngleType.ECCENTRIC,
67                  FramesFactory.getGCRF(), AbsoluteDate.ARBITRARY_EPOCH, mu);
68          final ForceModel mockedForce = Mockito.mock(ForceModel.class);
69          Mockito.when(mockedForce.dependsOnAttitudeRate()).thenReturn(dependsOnAttitudeRate);
70          Mockito.when(mockedForce.acceleration(Mockito.any(SpacecraftState.class), Mockito.any())).thenReturn(Vector3D.ZERO);
71          final TestContribution testContribution = new TestContribution("", 1., mockedForce,
72                  mu);
73          final SpacecraftState state = new SpacecraftState(orbit);
74          final AuxiliaryElements elements = new AuxiliaryElements(orbit, 1);
75          testContribution.registerAttitudeProvider(new FrameAlignedProvider(orbit.getFrame()));
76          // WHEN
77          final double[] rates = testContribution.getMeanElementRate(state, elements, new double[1]);
78          // THEN
79          Assertions.assertEquals(6, rates.length);
80      }
81  
82      @Test
83      @DisplayName("Coverage test for Field attitude building when depending on rate")
84      void testFieldGetMeanElementRateWhenDependingOnAttitudeRate() {
85          testTemplateFieldGetMeanElementRate(true);
86      }
87  
88      @Test
89      @DisplayName("Coverage test for Field attitude building when not depending on rate")
90      void testFieldGetMeanElementRateWhenNotDependingOnAttitudeRate() {
91          testTemplateFieldGetMeanElementRate(false);
92      }
93  
94      @SuppressWarnings("unchecked")
95      void testTemplateFieldGetMeanElementRate(final boolean dependsOnAttitudeRate) {
96          // GIVEN
97          final Field<Complex> field = ComplexField.getInstance();
98          final double mu = Constants.EIGEN5C_EARTH_MU;
99          final EquinoctialOrbit orbit = new EquinoctialOrbit(7e6, 0., 0.001, 0.01, 0., 0., PositionAngleType.ECCENTRIC,
100                 FramesFactory.getGCRF(), AbsoluteDate.ARBITRARY_EPOCH, mu);
101         final FieldOrbit<Complex> fieldOrbit = new FieldEquinoctialOrbit<>(field, orbit);
102         final ForceModel mockedForce = Mockito.mock(ForceModel.class);
103         Mockito.when(mockedForce.dependsOnAttitudeRate()).thenReturn(dependsOnAttitudeRate);
104         Mockito.when(mockedForce.acceleration(Mockito.any(FieldSpacecraftState.class), Mockito.any()))
105                 .thenReturn(FieldVector3D.getZero(field));
106         final TestContribution testContribution = new TestContribution("", 1., mockedForce,
107                 mu);
108         final FieldAuxiliaryElements<Complex> elements = new FieldAuxiliaryElements<>(fieldOrbit, 1);
109         testContribution.registerAttitudeProvider(new FrameAlignedProvider(orbit.getFrame()));
110         final Complex[] parameters = MathArrays.buildArray(field, 1);
111         parameters[0] = field.getOne();
112         // WHEN
113         final Complex[] rates = testContribution.getMeanElementRate(new FieldSpacecraftState<>(fieldOrbit), elements, parameters);
114         // THEN
115         Assertions.assertEquals(6, rates.length);
116     }
117 
118     private static class TestContribution extends AbstractGaussianContribution {
119 
120         protected TestContribution(String coefficientsKeyPrefix, double threshold, ForceModel contribution, double mu) {
121             super(coefficientsKeyPrefix, threshold, contribution, mu);
122         }
123 
124         @Override
125         protected List<ParameterDriver> getParametersDriversWithoutMu() {
126             return Collections.emptyList();
127         }
128 
129         @Override
130         protected double[] getLLimits(SpacecraftState state, AuxiliaryElements auxiliaryElements) {
131             return new double[] {0., 1.};
132         }
133 
134         @Override
135         protected <T extends CalculusFieldElement<T>> T[] getLLimits(FieldSpacecraftState<T> state, FieldAuxiliaryElements<T> auxiliaryElements) {
136             final Field<T> field = state.getDate().getField();
137             final T[] array = MathArrays.buildArray(field, 2);
138             array[0] = field.getZero();
139             array[1] = field.getOne();
140             return array;
141 
142         }
143     }
144 
145 }