Commit 0c31cab9 authored by Louis Aucouturier's avatar Louis Aucouturier
Browse files

Initial commit for Issue 826 : Correcting PropagatorParallelizer

behaviour for Numerical Propagators

- Modification were made on AbstractIntegratedPropagator and
PropagatorParallelizer to reach the last steps of the all threads.

- Simple tests were setup to check the behaviour.

- Performance might be impacted by the getGeneratedEphemeris calls, as
they now produce the ephemeris at each call.
parent 826358b8
......@@ -193,6 +193,16 @@ public class PropagatorsParallelizer {
} else {
// this was the last step
isLast = true;
/* For NumericalPropagators :
* After reaching the finalState with the selected monitor,
* we need to do the step with all remaining monitors to reach the target time.
* This also triggers the StoringStepHandler, producing ephemeris.
*/
for (PropagatorMonitoring monitor : monitors) {
if (monitor != selected) {
monitor.retrieveNextParameters();
}
}
}
previousDate = selectedStepEnd;
......@@ -407,6 +417,12 @@ public class PropagatorsParallelizer {
ParametersContainer params = null;
while (params == null && !future.isDone()) {
params = queue.poll(MAX_WAIT, TimeUnit.MILLISECONDS);
// Check to avoid loop on future not done, in the case of reached finalState.
if (parameters != null) {
if (parameters.finalState != null) {
break;
}
}
}
if (params == null) {
// call Future.get just for the side effect of retrieving the exception
......
......@@ -1048,6 +1048,9 @@ public abstract class AbstractIntegratedPropagator extends AbstractPropagator {
/** Generated ephemeris. */
private BoundedPropagator ephemeris;
/** Variable used to store the last interpolator handled by the object.*/
private ODEStateInterpolator lastInterpolator;
/** Set the end date.
* @param endDate end date
*/
......@@ -1065,11 +1068,15 @@ public abstract class AbstractIntegratedPropagator extends AbstractPropagator {
// ephemeris will be generated when last step is processed
this.ephemeris = null;
this.lastInterpolator = null;
}
/** {@inheritDoc} */
@Override
public BoundedPropagator getGeneratedEphemeris() {
// Each time we try to get the ephemeris, rebuild it using the last data.
buildEphemeris();
return ephemeris;
}
......@@ -1077,12 +1084,26 @@ public abstract class AbstractIntegratedPropagator extends AbstractPropagator {
@Override
public void handleStep(final ODEStateInterpolator interpolator) {
model.handleStep(interpolator);
lastInterpolator = interpolator;
}
/** {@inheritDoc} */
@Override
public void finish(final ODEStateAndDerivative finalState) {
buildEphemeris();
}
/** Method used to produce ephemeris at a given time.
* Can be used at multiple times, updating the ephemeris to
* its last state.
*/
private void buildEphemeris() {
// buildEphemeris was built in order to allow access to what was previously the finish method.
// This now allows to call it through getGeneratedEphemeris, therefore through an external call,
// which was not previously the case.
// Update the model's finalTime with the last interpolator.
model.finish(lastInterpolator.getCurrentState());
// set up the boundary dates
final double tI = model.getInitialTime();
final double tF = model.getFinalTime();
......
/* Copyright 2002-2022 CS GROUP
* Licensed to CS GROUP (CS) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* CS licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.orekit.propagation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import org.hipparchus.exception.LocalizedCoreFormats;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.ode.ODEIntegrator;
import org.hipparchus.ode.nonstiff.DormandPrince853Integrator;
import org.hipparchus.util.FastMath;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.orekit.Utils;
import org.orekit.attitudes.AttitudeProvider;
import org.orekit.attitudes.BodyCenterPointing;
import org.orekit.bodies.OneAxisEllipsoid;
import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitMessages;
import org.orekit.forces.ForceModel;
import org.orekit.forces.gravity.HolmesFeatherstoneAttractionModel;
import org.orekit.forces.gravity.potential.GravityFieldFactory;
import org.orekit.forces.gravity.potential.ICGEMFormatReader;
import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider;
import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider;
import org.orekit.frames.FramesFactory;
import org.orekit.orbits.KeplerianOrbit;
import org.orekit.orbits.Orbit;
import org.orekit.orbits.OrbitType;
import org.orekit.orbits.PositionAngle;
import org.orekit.propagation.analytical.EcksteinHechlerPropagator;
import org.orekit.propagation.events.DateDetector;
import org.orekit.propagation.events.handlers.StopOnEvent;
import org.orekit.propagation.integration.AdditionalDerivativesProvider;
import org.orekit.propagation.numerical.NumericalPropagator;
import org.orekit.propagation.semianalytical.dsst.DSSTPropagator;
import org.orekit.propagation.semianalytical.dsst.forces.DSSTForceModel;
import org.orekit.propagation.semianalytical.dsst.forces.DSSTZonal;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.DateComponents;
import org.orekit.time.TimeComponents;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.Constants;
import org.orekit.utils.IERSConventions;
public class PropagatorsParallelizerSeveralEphemerisTest {
/*
* Test set to check that ephemeris are produced at the end of the propagation parallelizer
* in the case of NuericalPropagators.
* Check existence of all ephemeris.
* Check end time of all ephemeris for varying step times.
*
* Should validate the modification, except for the retrieveNextParameters added check.
*
* Tests are based on Anne-Laure LUGAN's proposed test, and on PropagatorsParallelizerTest.
*/
@Test
public void testSeveralEphemeris() {
final AbsoluteDate startDate = orbit.getDate();
final AbsoluteDate endDate = startDate.shiftedBy(3600.0);
List<Propagator> propagators = Arrays.asList(buildNumerical(), buildNumerical(), buildNumerical());
List<EphemerisGenerator> generators = propagators.stream().map(Propagator::getEphemerisGenerator).collect(Collectors.toList());
PropagatorsParallelizer parallelizer = new PropagatorsParallelizer(propagators, interpolators -> {
// Do nothing
});
parallelizer.propagate(startDate, endDate);
generators.stream().forEach(generator -> Assert.assertNotNull(generator.getGeneratedEphemeris()));
}
@Test
public void testSeveralEphemeris2() {
final AbsoluteDate startDate = orbit.getDate();
final AbsoluteDate endDate = startDate.shiftedBy(3600.015);
List<Propagator> propagators = Arrays.asList(buildNumerical(1,300), buildNumerical(0.1,300), buildNumerical(0.001,300), buildEcksteinHechler());
List<EphemerisGenerator> generators = propagators.stream().map(Propagator::getEphemerisGenerator).collect(Collectors.toList());
PropagatorsParallelizer parallelizer = new PropagatorsParallelizer(propagators, interpolators -> {
// Do nothing
});
parallelizer.propagate(startDate, endDate);
generators.stream().forEach(generator -> Assert.assertNotNull(generator.getGeneratedEphemeris()));
AbsoluteDate lastDate = generators.get(0).getGeneratedEphemeris().getMaxDate();
for ( EphemerisGenerator generator : generators ) {
System.out.println(generator.getGeneratedEphemeris().getMaxDate());
Assert.assertEquals(lastDate, generator.getGeneratedEphemeris().getMaxDate());
}
}
private EcksteinHechlerPropagator buildEcksteinHechler() {
return new EcksteinHechlerPropagator(orbit, attitudeLaw, mass, unnormalizedGravityField);
}
private NumericalPropagator buildNumerical() {
return buildNumerical(0.001,300);
}
private NumericalPropagator buildNumerical(double minStep, double maxStep) {
NumericalPropagator numericalPropagator = buildNotInitializedNumerical(minStep, maxStep);
numericalPropagator.setInitialState(new SpacecraftState(orbit,
attitudeLaw.getAttitude(orbit,
orbit.getDate(),
orbit.getFrame()),
mass));
return numericalPropagator;
}
private NumericalPropagator buildNotInitializedNumerical(double minStep, double maxStep) {
OrbitType type = OrbitType.CARTESIAN;
double[][] tolerances = NumericalPropagator.tolerances(10.0, orbit, type);
ODEIntegrator integrator = new DormandPrince853Integrator(minStep, maxStep, tolerances[0], tolerances[1]);
NumericalPropagator numericalPropagator = new NumericalPropagator(integrator);
ForceModel gravity = new HolmesFeatherstoneAttractionModel(FramesFactory.getITRF(IERSConventions.IERS_2010, true),
normalizedGravityField);
numericalPropagator.addForceModel(gravity);
return numericalPropagator;
}
@Before
public void setUp() {
try {
Utils.setDataRoot("regular-data:potential/icgem-format");
unnormalizedGravityField = GravityFieldFactory.getUnnormalizedProvider(6, 0);
normalizedGravityField = GravityFieldFactory.getNormalizedProvider(6, 0);
mass = 2500;
double a = 7187990.1979844316;
double e = 0.5e-4;
double i = 1.7105407051081795;
double omega = 1.9674147913622104;
double OMEGA = FastMath.toRadians(261);
double lv = 0;
AbsoluteDate date = new AbsoluteDate(new DateComponents(2004, 01, 01),
TimeComponents.H00,
TimeScalesFactory.getUTC());
orbit = new KeplerianOrbit(a, e, i, omega, OMEGA, lv, PositionAngle.TRUE,
FramesFactory.getEME2000(), date, normalizedGravityField.getMu());
OneAxisEllipsoid earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
Constants.WGS84_EARTH_FLATTENING,
FramesFactory.getITRF(IERSConventions.IERS_2010, true));
attitudeLaw = new BodyCenterPointing(orbit.getFrame(), earth);
} catch (OrekitException oe) {
Assert.fail(oe.getLocalizedMessage());
}
}
@After
public void tearDown() {
mass = Double.NaN;
orbit = null;
attitudeLaw = null;
unnormalizedGravityField = null;
normalizedGravityField = null;
}
private double mass;
private Orbit orbit;
private AttitudeProvider attitudeLaw;
private UnnormalizedSphericalHarmonicsProvider unnormalizedGravityField;
private NormalizedSphericalHarmonicsProvider normalizedGravityField;
}
......@@ -17,9 +17,11 @@
package org.orekit.propagation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import org.hipparchus.exception.LocalizedCoreFormats;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment