From 8fa3992941f9ec23fc83a98df205a82bd0974c8d Mon Sep 17 00:00:00 2001 From: Daniel Lisunkin Date: Tue, 28 May 2019 13:40:18 +0200 Subject: [PATCH] Started implementing the getImpliedWindNewton() method of ORCPerformanceCurveImpl. Goal is to analyse the difference of the accuracy with this method in comparison to the ORC way. --- .../domain/orc/TestORCPerformanceCurve.java | 30 +++++++++++++++++-- .../orc/impl/ORCPerformanceCurveImpl.java | 23 ++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/orc/TestORCPerformanceCurve.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/orc/TestORCPerformanceCurve.java index fb4c7ada217..d92cd5a69e5 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/orc/TestORCPerformanceCurve.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/orc/TestORCPerformanceCurve.java @@ -11,6 +11,7 @@ import java.util.Map; import org.apache.commons.math.ArgumentOutsideDomainException; import org.apache.commons.math.FunctionEvaluationException; +import org.apache.commons.math.MaxIterationsExceededException; import org.json.simple.parser.ParseException; import org.junit.Assert; import org.junit.BeforeClass; @@ -137,9 +138,32 @@ public class TestORCPerformanceCurve { ORCPerformanceCurveImpl performanceCurve = (ORCPerformanceCurveImpl) certificate.getPerformanceCurve(course); - assertEquals(6, performanceCurve.getImpliedWind(performanceCurve.getAllowancePerCourse(new KnotSpeedImpl(6))).getKnots(), accuracy); - assertEquals(11.5, performanceCurve.getImpliedWind(performanceCurve.getAllowancePerCourse(new KnotSpeedImpl(11.5))).getKnots(), accuracy); + assertEquals( 6, performanceCurve.getImpliedWind(performanceCurve.getAllowancePerCourse(new KnotSpeedImpl( 6))).getKnots(), accuracy); + assertEquals( 11.5, performanceCurve.getImpliedWind(performanceCurve.getAllowancePerCourse(new KnotSpeedImpl( 11.5))).getKnots(), accuracy); assertEquals(17.23, performanceCurve.getImpliedWind(performanceCurve.getAllowancePerCourse(new KnotSpeedImpl(17.23))).getKnots(), accuracy); - } + + assertEquals( 500, performanceCurve.getAllowancePerCourse(performanceCurve.getImpliedWind(Duration.ONE_SECOND.times(500))).asSeconds(), accuracy); + assertEquals( 600, performanceCurve.getAllowancePerCourse(performanceCurve.getImpliedWind(Duration.ONE_SECOND.times(600))).asSeconds(), accuracy); + assertEquals( 700, performanceCurve.getAllowancePerCourse(performanceCurve.getImpliedWind(Duration.ONE_SECOND.times(700))).asSeconds(), accuracy); + } + + @Test + public void testPerformanceCurveInvertationNewton() throws MaxIterationsExceededException, FunctionEvaluationException { + System.out.println("- testPerformanceCurveInvertationNewton() -"); + Double accuracy = 0.1; + ORCCertificateImpl certificate = (ORCCertificateImpl) importer.getCertificate("GER 5549"); + ORCPerformanceCurveImpl performanceCurve = (ORCPerformanceCurveImpl) certificate.getPerformanceCurve(course); + + + //assertEquals( 6, performanceCurve.getImpliedWindNewton(performanceCurve.getAllowancePerCourse(new KnotSpeedImpl( 6))).getKnots(), accuracy); + assertEquals( 11.5, performanceCurve.getImpliedWindNewton(performanceCurve.getAllowancePerCourse(new KnotSpeedImpl( 11.5))).getKnots(), accuracy); + assertEquals(17.23, performanceCurve.getImpliedWindNewton(performanceCurve.getAllowancePerCourse(new KnotSpeedImpl(17.23))).getKnots(), accuracy); + + /* + assertEquals( 500, performanceCurve.getAllowancePerCourse(performanceCurve.getImpliedWindNewton(Duration.ONE_SECOND.times(500))).asSeconds(), accuracy); + assertEquals( 600, performanceCurve.getAllowancePerCourse(performanceCurve.getImpliedWindNewton(Duration.ONE_SECOND.times(600))).asSeconds(), accuracy); + assertEquals( 700, performanceCurve.getAllowancePerCourse(performanceCurve.getImpliedWindNewton(Duration.ONE_SECOND.times(700))).asSeconds(), accuracy); + */ + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCPerformanceCurveImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCPerformanceCurveImpl.java index d3dc8ad6248..0b329c6f50c 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCPerformanceCurveImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCPerformanceCurveImpl.java @@ -13,9 +13,12 @@ import java.util.Map.Entry; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.math.ArgumentOutsideDomainException; import org.apache.commons.math.FunctionEvaluationException; +import org.apache.commons.math.MaxIterationsExceededException; import org.apache.commons.math.analysis.interpolation.SplineInterpolator; +import org.apache.commons.math.analysis.polynomials.PolynomialFunction; import org.apache.commons.math.analysis.polynomials.PolynomialFunctionLagrangeForm; import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction; +import org.apache.commons.math.analysis.solvers.NewtonSolver; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.impl.KnotSpeedImpl; @@ -204,6 +207,26 @@ public class ORCPerformanceCurveImpl implements Serializable, ORCPerformanceCurv return new KnotSpeedImpl(functionAllowanceToTwa.value(time.asSeconds())); } + public Speed getImpliedWindNewton(Duration time) throws MaxIterationsExceededException, FunctionEvaluationException { + PolynomialFunction workingFunction; + double[] allowances = new double[functionTwaToAllowance.getKnots().length]; + + for (int i = 0; i < allowances.length; i++) { + allowances[i] = functionTwaToAllowance.value(functionTwaToAllowance.getKnots()[i]); + } + + int i = 0; + while(i < allowances.length && time.asSeconds() <= allowances[i]) { + i += 1; + } + i -= 1; + workingFunction = functionTwaToAllowance.getPolynomials()[i-1]; + + NewtonSolver solver = new NewtonSolver(workingFunction.subtract(new PolynomialFunction(new double[] {time.asSeconds()}))); + solver.setAbsoluteAccuracy(0.000001); + return new KnotSpeedImpl(solver.solve(functionTwaToAllowance.getKnots()[i], functionTwaToAllowance.getKnots()[i+1])); + } + public Duration getAllowancePerCourse(Speed twa) throws ArgumentOutsideDomainException { return Duration.ONE_SECOND.times(functionTwaToAllowance.value(twa.getKnots())); }