Commit 95486859 authored by Bryan Cazabonne's avatar Bryan Cazabonne
Browse files

Merge remote-tracking branch 'origin/port-fix-hipparchus-184' into

pre-release
parents e2632834 2ab09f0f
......@@ -50,7 +50,7 @@
<orekit.maven-install-plugin.version>3.0.0-M1</orekit.maven-install-plugin.version>
<orekit.mathjax.config>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;MathJax.Hub.Config({ TeX: { extensions: [&quot;autoload.js&quot;]}});&lt;/script&gt;</orekit.mathjax.config>
<orekit.mathjax.enable>&lt;script type=&quot;text/javascript&quot; src=&quot;https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS_CHTML&quot;&gt;&lt;/script&gt;</orekit.mathjax.enable>
<orekit.hipparchus.version>2.0</orekit.hipparchus.version>
<orekit.hipparchus.version>2.1-SNAPSHOT</orekit.hipparchus.version>
<orekit.junit.version>4.13.2</orekit.junit.version>
<orekit.compiler.source>1.8</orekit.compiler.source>
<orekit.compiler.target>1.8</orekit.compiler.target>
......
......@@ -55,6 +55,10 @@
<action dev="evan" type="fix" issue="912">
Fix StreamingOemWriter without acceleration.
</action>
<action dev="luc" type="fix" issue="184">
Fixed non-bracketing issue when RESET_STATE slightly moves an event at the start
of a step and another regular event happens in the first half of the same step
</action>
</release>
<release version="11.1.1" date="2022-03-17"
description="Version 11.1.1 is a patch release of Orekit.
......
......@@ -259,6 +259,10 @@ public class EventState<T extends EventDetector> {
final BracketedUnivariateSolver<UnivariateFunction> solver =
new BracketingNthOrderBrentSolver(0, convergence, 0, 5);
// prepare loop below
AbsoluteDate loopT = ta;
double loopG = ga;
// event time, just at or before the actual root.
AbsoluteDate beforeRootT = null;
double beforeRootG = Double.NaN;
......@@ -288,17 +292,26 @@ public class EventState<T extends EventDetector> {
final double newGa = g(interpolator.getInterpolatedState(ta));
if (ga > 0 != newGa > 0) {
// both non-zero, step sign change at ta, possibly due to reset state
beforeRootT = ta;
beforeRootG = newGa;
afterRootT = minTime(shiftedBy(beforeRootT, convergence), tb);
afterRootG = g(interpolator.getInterpolatedState(afterRootT));
final AbsoluteDate nextT = minTime(shiftedBy(ta, convergence), tb);
final double nextG = g(interpolator.getInterpolatedState(nextT));
if (nextG > 0.0 == g0Positive) {
// the sign change between ga and newGa just moved the root less than one convergence
// threshold later, we are still in a regular search for another root before tb,
// we just need to fix the bracketing interval
// (see issue https://github.com/Hipparchus-Math/hipparchus/issues/184)
loopT = nextT;
loopG = nextG;
} else {
beforeRootT = ta;
beforeRootG = newGa;
afterRootT = nextT;
afterRootG = nextG;
}
}
}
// loop to skip through "fake" roots, i.e. where g(t) = g'(t) = 0.0
// executed once if we didn't hit a special case above
AbsoluteDate loopT = ta;
double loopG = ga;
while ((afterRootG == 0.0 || afterRootG > 0.0 == g0Positive) &&
strictlyAfter(afterRootT, tb)) {
if (loopG == 0.0) {
......
......@@ -265,6 +265,10 @@ public class FieldEventState<D extends FieldEventDetector<T>, T extends Calculus
final BracketedUnivariateSolver<UnivariateFunction> solver =
new BracketingNthOrderBrentSolver(0, convergence.getReal(), 0, 5);
// prepare loop below
FieldAbsoluteDate<T> loopT = ta;
T loopG = ga;
// event time, just at or before the actual root.
FieldAbsoluteDate<T> beforeRootT = null;
T beforeRootG = zero.add(Double.NaN);
......@@ -294,16 +298,26 @@ public class FieldEventState<D extends FieldEventDetector<T>, T extends Calculus
final T newGa = g(interpolator.getInterpolatedState(ta));
if (ga.getReal() > 0 != newGa.getReal() > 0) {
// both non-zero, step sign change at ta, possibly due to reset state
beforeRootT = ta;
beforeRootG = newGa;
afterRootT = minTime(shiftedBy(beforeRootT, convergence), tb);
afterRootG = g(interpolator.getInterpolatedState(afterRootT));
final FieldAbsoluteDate<T> nextT = minTime(shiftedBy(ta, convergence), tb);
final T nextG = g(interpolator.getInterpolatedState(nextT));
if (nextG.getReal() > 0.0 == g0Positive) {
// the sign change between ga and newGa just moved the root less than one convergence
// threshold later, we are still in a regular search for another root before tb,
// we just need to fix the bracketing interval
// (see issue https://github.com/Hipparchus-Math/hipparchus/issues/184)
loopT = nextT;
loopG = nextG;
} else {
beforeRootT = ta;
beforeRootG = newGa;
afterRootT = nextT;
afterRootG = nextG;
}
}
}
// loop to skip through "fake" roots, i.e. where g(t) = g'(t) = 0.0
// executed once if we didn't hit a special case above
FieldAbsoluteDate<T> loopT = ta;
T loopG = ga;
while ((afterRootG.getReal() == 0.0 || afterRootG.getReal() > 0.0 == g0Positive) &&
strictlyAfter(afterRootT, tb)) {
if (loopG.getReal() == 0.0) {
......
......@@ -33,6 +33,7 @@ import org.orekit.orbits.KeplerianOrbit;
import org.orekit.orbits.PositionAngle;
import org.orekit.propagation.Propagator;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.events.handlers.ContinueOnEvent;
import org.orekit.propagation.events.handlers.EventHandler;
import org.orekit.propagation.events.handlers.RecordAndContinue;
import org.orekit.propagation.events.handlers.RecordAndContinue.Event;
......@@ -2117,6 +2118,20 @@ public abstract class CloseEventsAbstractTest {
}
}
@Test
public void testResetChangesSign() {
Propagator propagator = getPropagator(2.5);
AbsoluteDate t0 = propagator.getInitialState().getDate();
final double small = 1.25e-11;
ResetChangesSignGenerator eventsGenerator = new ResetChangesSignGenerator(t0, 0.75, 1.125, -0.5 * small).
withMaxCheck(1).
withThreshold(small).
withMaxIter(1000);
propagator.addEventDetector(eventsGenerator);
final SpacecraftState end = propagator.propagate(propagator.getInitialState().getDate().shiftedBy(12.5));
Assert.assertEquals(2, eventsGenerator.getCount());
Assert.assertEquals(1.125 + 0.5 * small, end.getDate().durationFrom(t0), 1.0e-12);
}
/* utility classes and methods */
......@@ -2375,4 +2390,57 @@ public abstract class CloseEventsAbstractTest {
}
}
private class ResetChangesSignGenerator extends AbstractDetector<ResetChangesSignGenerator> {
final AbsoluteDate t0;
final double y1;
final double y2;
final double change;
double delta;
int count;
public ResetChangesSignGenerator(final AbsoluteDate t0, final double y1, final double y2, final double change) {
this(DEFAULT_MAXCHECK, DEFAULT_THRESHOLD, DEFAULT_MAX_ITER,
new ContinueOnEvent<>(), t0, y1, y2, change);
}
private ResetChangesSignGenerator(final double newMaxCheck, final double newThreshold, final int newMaxIter,
final EventHandler<? super ResetChangesSignGenerator> newHandler,
final AbsoluteDate t0, final double y1, final double y2, final double change ) {
super(newMaxCheck, newThreshold, newMaxIter, newHandler);
this.t0 = t0;
this.y1 = y1;
this.y2 = y2;
this.change = change;
this.delta = 0;
this.count = 0;
}
protected ResetChangesSignGenerator create(final double newMaxCheck, final double newThreshold,
final int newMaxIter,
final EventHandler<? super ResetChangesSignGenerator> newHandler) {
return new ResetChangesSignGenerator(newMaxCheck, newThreshold, newMaxIter, newHandler,
t0, y1, y2, change);
}
public double g(SpacecraftState s) {
double dt = s.getDate().durationFrom(t0) + delta;
return (dt - y1) * (dt - y2);
}
public Action eventOccurred(SpacecraftState s, boolean increasing) {
return ++count < 2 ? Action.RESET_STATE : Action.STOP;
}
public SpacecraftState resetState(SpacecraftState s) {
delta = change;
return s;
}
public int getCount() {
return count;
}
}
}
......@@ -20,8 +20,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.hipparchus.Field;
import org.hipparchus.CalculusFieldElement;
import org.hipparchus.Field;
import org.hipparchus.ode.events.Action;
import org.hipparchus.util.FastMath;
import org.junit.Assert;
......@@ -37,6 +37,7 @@ import org.orekit.propagation.FieldPropagator;
import org.orekit.propagation.FieldSpacecraftState;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.events.handlers.EventHandler;
import org.orekit.propagation.events.handlers.FieldContinueOnEvent;
import org.orekit.propagation.events.handlers.FieldEventHandler;
import org.orekit.propagation.events.handlers.FieldRecordAndContinue;
import org.orekit.propagation.events.handlers.FieldRecordAndContinue.Event;
......@@ -2335,7 +2336,20 @@ public abstract class FieldCloseEventsAbstractTest<T extends CalculusFieldElemen
}
}
@Test
public void testResetChangesSign() {
FieldPropagator<T> propagator = getPropagator(2.5);
FieldAbsoluteDate<T> t0 = propagator.getInitialState().getDate();
final double small = 1.25e-11;
ResetChangesSignGenerator eventsGenerator = new ResetChangesSignGenerator(t0, 0.75, 1.125, -0.5 * small).
withMaxCheck(t0.getField().getZero().newInstance(1)).
withThreshold(t0.getField().getZero().newInstance(small)).
withMaxIter(1000);
propagator.addEventDetector(eventsGenerator);
final FieldSpacecraftState<T> end = propagator.propagate(propagator.getInitialState().getDate().shiftedBy(12.5));
Assert.assertEquals(2, eventsGenerator.getCount());
Assert.assertEquals(1.125 + 0.5 * small, end.getDate().durationFrom(t0).getReal(), 1.0e-12);
}
/* utility classes and methods */
......@@ -2609,4 +2623,58 @@ public abstract class FieldCloseEventsAbstractTest<T extends CalculusFieldElemen
}
}
private class ResetChangesSignGenerator extends FieldAbstractDetector<ResetChangesSignGenerator, T> {
final FieldAbsoluteDate<T> t0;
final double y1;
final double y2;
final double change;
double delta;
int count;
public ResetChangesSignGenerator(final FieldAbsoluteDate<T> t0, final double y1, final double y2, final double change) {
this(t0.getField().getZero().newInstance(DEFAULT_MAXCHECK),
t0.getField().getZero().newInstance(DEFAULT_THRESHOLD),
DEFAULT_MAX_ITER,
new FieldContinueOnEvent<>(), t0, y1, y2, change);
}
private ResetChangesSignGenerator(final T newMaxCheck, final T newThreshold, final int newMaxIter,
final FieldEventHandler<? super ResetChangesSignGenerator, T> newHandler,
final FieldAbsoluteDate<T> t0, final double y1, final double y2, final double change ) {
super(newMaxCheck, newThreshold, newMaxIter, newHandler);
this.t0 = t0;
this.y1 = y1;
this.y2 = y2;
this.change = change;
this.delta = 0;
this.count = 0;
}
protected ResetChangesSignGenerator create(final T newMaxCheck, final T newThreshold, final int newMaxIter,
final FieldEventHandler<? super ResetChangesSignGenerator, T> newHandler) {
return new ResetChangesSignGenerator(newMaxCheck, newThreshold, newMaxIter, newHandler,
t0, y1, y2, change);
}
public T g(FieldSpacecraftState<T> s) {
T dt = s.getDate().durationFrom(t0).add(delta);
return dt.subtract(y1).multiply(dt.subtract(y2));
}
public Action eventOccurred(FieldSpacecraftState<T> s, boolean increasing) {
return ++count < 2 ? Action.RESET_STATE : Action.STOP;
}
public FieldSpacecraftState<T> resetState(FieldSpacecraftState<T> s) {
delta = change;
return s;
}
public int getCount() {
return count;
}
}
}
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