Author: luc
Date: Sun Apr 20 14:29:42 2014
New Revision: 1588769

URL: http://svn.apache.org/r1588769
Log:
Added a fast single-step method for fixed-step Runge-Kutta integrators.

JIRA: MATH-1119

Modified:
    commons/proper/math/trunk/src/changes/changes.xml
    
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/ode/nonstiff/RungeKuttaIntegrator.java
    
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/ode/nonstiff/LutherIntegratorTest.java

Modified: commons/proper/math/trunk/src/changes/changes.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/changes/changes.xml?rev=1588769&r1=1588768&r2=1588769&view=diff
==============================================================================
--- commons/proper/math/trunk/src/changes/changes.xml (original)
+++ commons/proper/math/trunk/src/changes/changes.xml Sun Apr 20 14:29:42 2014
@@ -51,6 +51,9 @@ If the output is not quite correct, chec
   </properties>
   <body>
     <release version="3.3" date="TBD" description="TBD">
+      <action dev="luc" type="add" issue="MATH-1119">
+        Added a fast single-step method for fixed-step Runge-Kutta integrators.
+      </action>
       <action dev="erans" type="fix" issue="MATH-1118">
         "Complex": Fixed compatibility of "equals(Object)" with "hashCode()".
         Added new methods for testing floating-point equality between the real

Modified: 
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/ode/nonstiff/RungeKuttaIntegrator.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/ode/nonstiff/RungeKuttaIntegrator.java?rev=1588769&r1=1588768&r2=1588769&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/ode/nonstiff/RungeKuttaIntegrator.java
 (original)
+++ 
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/ode/nonstiff/RungeKuttaIntegrator.java
 Sun Apr 20 14:29:42 2014
@@ -24,6 +24,7 @@ import org.apache.commons.math3.exceptio
 import org.apache.commons.math3.exception.NumberIsTooSmallException;
 import org.apache.commons.math3.ode.AbstractIntegrator;
 import org.apache.commons.math3.ode.ExpandableStatefulODE;
+import org.apache.commons.math3.ode.FirstOrderDifferentialEquations;
 import org.apache.commons.math3.util.FastMath;
 
 /**
@@ -185,4 +186,73 @@ public abstract class RungeKuttaIntegrat
 
   }
 
+  /** Fast computation of a single step of ODE integration.
+   * <p>This method is intended for the limited use case of
+   * very fast computation of only one step without using any of the
+   * rich features of general integrators that may take some time
+   * to set up (i.e. no step handlers, no events handlers, no additional
+   * states, no interpolators, no error control, no evaluations count,
+   * no sanity checks ...). It handles the strict minimum of computation,
+   * so it can be embedded in outer loops.</p>
+   * <p>
+   * This method is <em>not</em> used at all by the {@link 
#integrate(ExpandableStatefulODE, double)}
+   * method. It also completely ignores the step set at construction time, and
+   * uses only a single step to go from {@code t0} to {@code t}.
+   * </p>
+   * <p>
+   * As this method does not use any of the state-dependent features of the 
integrator,
+   * it should be reasonably thread-safe <em>if and only if</em> the provided 
differential
+   * equations are themselves thread-safe.
+   * </p>
+   * @param equations differential equations to integrate
+   * @param t0 initial time
+   * @param y0 initial value of the state vector at t0
+   * @param t target time for the integration
+   * (can be set to a value smaller than {@code t0} for backward integration)
+   * @return state vector at {@code t}
+   */
+  public double[] singleStep(final FirstOrderDifferentialEquations equations,
+                             final double t0, final double[] y0, final double 
t) {
+
+      // create some internal working arrays
+      final double[] y       = y0.clone();
+      final int stages       = c.length + 1;
+      final double[][] yDotK = new double[stages][];
+      for (int i = 0; i < stages; ++i) {
+          yDotK [i] = new double[y0.length];
+      }
+      final double[] yTmp    = y0.clone();
+
+      // first stage
+      final double h = t - t0;
+      equations.computeDerivatives(t0, y, yDotK[0]);
+
+      // next stages
+      for (int k = 1; k < stages; ++k) {
+
+          for (int j = 0; j < y0.length; ++j) {
+              double sum = a[k-1][0] * yDotK[0][j];
+              for (int l = 1; l < k; ++l) {
+                  sum += a[k-1][l] * yDotK[l][j];
+              }
+              yTmp[j] = y[j] + h * sum;
+          }
+
+          equations.computeDerivatives(t0 + c[k-1] * h, yTmp, yDotK[k]);
+
+      }
+
+      // estimate the state at the end of the step
+      for (int j = 0; j < y0.length; ++j) {
+          double sum = b[0] * yDotK[0][j];
+          for (int l = 1; l < stages; ++l) {
+              sum += b[l] * yDotK[l][j];
+          }
+          y[j] += h * sum;
+      }
+
+      return y;
+
+  }
+
 }

Modified: 
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/ode/nonstiff/LutherIntegratorTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/ode/nonstiff/LutherIntegratorTest.java?rev=1588769&r1=1588768&r2=1588769&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/ode/nonstiff/LutherIntegratorTest.java
 (original)
+++ 
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/ode/nonstiff/LutherIntegratorTest.java
 Sun Apr 20 14:29:42 2014
@@ -306,4 +306,24 @@ public class LutherIntegratorTest {
         }, 0.0, new double[] { 0.0 }, 5.0, new double[1]);
     }
 
+    @Test
+    public void testSingleStep() {
+
+        final TestProblem3 pb  = new TestProblem3(0.9);
+        double h = (pb.getFinalTime() - pb.getInitialTime()) * 0.0003;
+
+        RungeKuttaIntegrator integ = new LutherIntegrator(Double.NaN);
+        double   t = pb.getInitialTime();
+        double[] y = pb.getInitialState();
+        for (int i = 0; i < 100; ++i) {
+            y = integ.singleStep(pb, t, y, t + h);
+            t += h;
+        }
+        double[] yth = pb.computeTheoreticalState(t);
+        double dx = y[0] - yth[0];
+        double dy = y[1] - yth[1];
+        double error = dx * dx + dy * dy;
+        Assert.assertEquals(0.0, error, 1.0e-11);
+    }
+
 }


Reply via email to