1   /* Copyright 2002-2025 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  
18  package org.orekit.propagation.conversion;
19  
20  import org.hipparchus.geometry.euclidean.threed.Vector3D;
21  import org.junit.jupiter.api.Assertions;
22  import org.junit.jupiter.api.BeforeAll;
23  import org.junit.jupiter.api.Test;
24  import org.mockito.Mockito;
25  import org.orekit.Utils;
26  import org.orekit.forces.ForceModel;
27  import org.orekit.forces.gravity.HolmesFeatherstoneAttractionModel;
28  import org.orekit.forces.gravity.potential.GravityFieldFactory;
29  import org.orekit.forces.maneuvers.ImpulseManeuver;
30  import org.orekit.frames.FramesFactory;
31  import org.orekit.orbits.CartesianOrbit;
32  import org.orekit.orbits.Orbit;
33  import org.orekit.orbits.PositionAngleType;
34  import org.orekit.propagation.Propagator;
35  import org.orekit.propagation.events.EventDetector;
36  import org.orekit.time.AbsoluteDate;
37  import org.orekit.utils.Constants;
38  import org.orekit.utils.IERSConventions;
39  import org.orekit.utils.PVCoordinates;
40  import org.orekit.utils.TimeStampedPVCoordinates;
41  
42  import java.util.Collection;
43  import java.util.List;
44  
45  import static org.orekit.propagation.conversion.AbstractPropagatorBuilderTest.assertPropagatorBuilderIsACopy;
46  
47  public class NumericalPropagatorBuilderTest {
48  
49      @BeforeAll
50      public static void setUpBeforeClass() {
51          Utils.setDataRoot("regular-data:potential");
52      }
53  
54      @Test
55      void testClearImpulseManeuvers() {
56          // Given
57          final ODEIntegratorBuilder integratorBuilder = new ClassicalRungeKuttaIntegratorBuilder(60);
58          final Orbit orbit = getOrbit();
59          final NumericalPropagatorBuilder builder =
60                  new NumericalPropagatorBuilder(orbit, integratorBuilder, PositionAngleType.MEAN, 1.0, Utils.defaultLaw());
61          final ImpulseManeuver mockedManeuver = Mockito.mock(ImpulseManeuver.class);
62          builder.addImpulseManeuver(mockedManeuver);
63          // WHEN
64          builder.clearImpulseManeuvers();
65          // THEN
66          final Propagator propagator = builder.buildPropagator();
67          final Collection<EventDetector> detectors = propagator.getEventDetectors();
68          Assertions.assertTrue(detectors.isEmpty());
69      }
70  
71      @Test
72      void testAddImpulseManeuver() {
73          // Given
74          final ODEIntegratorBuilder integratorBuilder = new ClassicalRungeKuttaIntegratorBuilder(60);
75          final Orbit orbit = getOrbit();
76          final NumericalPropagatorBuilder builder =
77                  new NumericalPropagatorBuilder(orbit, integratorBuilder, PositionAngleType.MEAN, 1.0, Utils.defaultLaw());
78          final ImpulseManeuver mockedManeuver = Mockito.mock(ImpulseManeuver.class);
79          // WHEN
80          builder.addImpulseManeuver(mockedManeuver);
81          // THEN
82          final Propagator propagator = builder.buildPropagator();
83          final Collection<EventDetector> detectors = propagator.getEventDetectors();
84          Assertions.assertEquals(1, detectors.size());
85          Assertions.assertEquals(mockedManeuver, detectors.toArray()[0]);
86      }
87  
88      @Test
89      void testClone() {
90  
91          // Given
92          final ODEIntegratorBuilder integratorBuilder = new ClassicalRungeKuttaIntegratorBuilder(60);
93          final Orbit orbit = getOrbit();
94  
95          final NumericalPropagatorBuilder builder =
96                  new NumericalPropagatorBuilder(orbit, integratorBuilder, PositionAngleType.MEAN, 1.0, Utils.defaultLaw());
97  
98          builder.addForceModel(new HolmesFeatherstoneAttractionModel(FramesFactory.getITRF(IERSConventions.IERS_2010, true),
99                  GravityFieldFactory.getNormalizedProvider(2, 0)));
100 
101         // Select propagation parameters to test this point
102         builder.getPropagationParametersDrivers().getDrivers().forEach(d -> d.setSelected(true));
103 
104         // When
105         final NumericalPropagatorBuilder copyBuilder = builder.clone();
106 
107         // Then
108         assertNumericalPropagatorBuilderIsACopy(builder, copyBuilder);
109     }
110 
111     /** Test for issue #1741.
112      * <p>This test checks that orbital drivers in cloned propagator builders
113      * ain't at the same physical address, i.e. that they're not linked anymore.</p>
114      */
115     @Test
116     void testIssue1741() {
117 
118         // Given
119         final ODEIntegratorBuilder integratorBuilder = new ClassicalRungeKuttaIntegratorBuilder(60);
120         final Orbit orbit = getOrbit();
121 
122         final NumericalPropagatorBuilder builder =
123                         new NumericalPropagatorBuilder(orbit, integratorBuilder, PositionAngleType.MEAN, 1.0, Utils.defaultLaw());
124 
125         builder.addForceModel(new HolmesFeatherstoneAttractionModel(FramesFactory.getITRF(IERSConventions.IERS_2010, true),
126                                                                     GravityFieldFactory.getNormalizedProvider(2, 0)));
127 
128         // When
129         final PropagatorBuilder copyBuilder = builder.clone();
130 
131         // Change orbit of the copied builder
132         final TimeStampedPVCoordinates modifiedPv = orbit.shiftedBy(3600.).getPVCoordinates();
133         copyBuilder.resetOrbit(new CartesianOrbit(modifiedPv, orbit.getFrame(), orbit.getDate(), orbit.getMu()));
134 
135 
136         // Then
137         // Original builder should still have original orbit
138         final PVCoordinates originalPv = orbit.getPVCoordinates();
139         final PVCoordinates initialPv = builder.createInitialOrbit().getPVCoordinates();
140         final double dP = originalPv.getPosition().distance(initialPv.getPosition());
141         final double dV = originalPv.getVelocity().distance(initialPv.getVelocity());
142         final double dA = originalPv.getAcceleration().distance(initialPv.getAcceleration());
143         Assertions.assertEquals(0., dP, 0.);
144         Assertions.assertEquals(0., dV, 0.);
145         Assertions.assertEquals(0., dA, 0.);
146     }
147 
148     private static Orbit getOrbit() {
149         return new CartesianOrbit(new PVCoordinates(
150                 new Vector3D(Constants.EIGEN5C_EARTH_EQUATORIAL_RADIUS + 400000, 0, 0),
151                 new Vector3D(0, 7668.6, 0)), FramesFactory.getGCRF(),
152                 new AbsoluteDate(), Constants.EIGEN5C_EARTH_MU);
153     }
154 
155     private void assertNumericalPropagatorBuilderIsACopy(final NumericalPropagatorBuilder expected,
156                                                          final NumericalPropagatorBuilder actual) {
157         assertPropagatorBuilderIsACopy(expected, actual);
158 
159         // Assert force models
160         final List<ForceModel> expectedForceModelList = expected.getAllForceModels();
161         final List<ForceModel> actualForceModelList   = actual.getAllForceModels();
162         Assertions.assertEquals(expectedForceModelList.size(), actualForceModelList.size());
163         for (int i = 0; i < expectedForceModelList.size(); i++) {
164             Assertions.assertEquals(expectedForceModelList.get(i).getClass(), actualForceModelList.get(i).getClass());
165         }
166 
167         // Assert integrator builder
168         Assertions.assertEquals(expected.getIntegratorBuilder().getClass(), actual.getIntegratorBuilder().getClass());
169 
170         // Assert mass
171         Assertions.assertEquals(expected.getMass(), actual.getMass());
172     }
173 
174 }