You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by lu...@apache.org on 2007/02/27 00:12:45 UTC

svn commit: r512066 [4/5] - in /jakarta/commons/proper/math/trunk/src: java/org/apache/commons/math/ode/ mantissa/src/org/spaceroots/mantissa/ode/ mantissa/src/org/spaceroots/mantissa/ode/doc-files/ mantissa/tests-src/org/spaceroots/mantissa/ode/ test/...

Added: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/RungeKuttaIntegrator.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/RungeKuttaIntegrator.java?view=auto&rev=512066
==============================================================================
--- jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/RungeKuttaIntegrator.java (added)
+++ jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/RungeKuttaIntegrator.java Mon Feb 26 15:12:40 2007
@@ -0,0 +1,279 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF 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.apache.commons.math.ode;
+
+/**
+ * This class implements the common part of all fixed step Runge-Kutta
+ * integrators for Ordinary Differential Equations.
+
+ * <p>These methods are explicit Runge-Kutta methods, their Butcher
+ * arrays are as follows :
+ * <pre>
+ *    0  |
+ *   c2  | a21
+ *   c3  | a31  a32
+ *   ... |        ...
+ *   cs  | as1  as2  ...  ass-1
+ *       |--------------------------
+ *       |  b1   b2  ...   bs-1  bs
+ * </pre>
+ * </p>
+
+ * <p>Some methods are qualified as <i>fsal</i> (first same as last)
+ * methods. This means the last evaluation of the derivatives in one
+ * step is the same as the first in the next step. Then, this
+ * evaluation can be reused from one step to the next one and the cost
+ * of such a method is really s-1 evaluations despite the method still
+ * has s stages. This behaviour is true only for successful steps, if
+ * the step is rejected after the error estimation phase, no
+ * evaluation is saved. For an <i>fsal</i> method, we have cs = 1 and
+ * asi = bi for all i.</p>
+
+ * @see EulerIntegrator
+ * @see ClassicalRungeKuttaIntegrator
+ * @see GillIntegrator
+ * @see MidpointIntegrator
+
+ * @version $Id: RungeKuttaIntegrator.java 1705 2006-09-17 19:57:39Z luc $
+ * @author L. Maisonobe
+
+ */
+
+public abstract class RungeKuttaIntegrator
+  implements FirstOrderIntegrator {
+
+  /** Simple constructor.
+   * Build a Runge-Kutta integrator with the given
+   * step. The default step handler does nothing.
+   * @param fsal indicate that the method is an <i>fsal</i>
+   * @param c time steps from Butcher array (without the first zero)
+   * @param a internal weights from Butcher array (without the first empty row)
+   * @param b external weights for the high order method from Butcher array
+   * @param prototype prototype of the step interpolator to use
+   * @param step integration step
+   */
+  protected RungeKuttaIntegrator(boolean fsal,
+                                 double[] c, double[][] a, double[] b,
+                                 RungeKuttaStepInterpolator prototype,
+                                 double step) {
+    this.fsal       = fsal;
+    this.c          = c;
+    this.a          = a;
+    this.b          = b;
+    this.prototype  = prototype;
+    this.step       = step;
+    handler         = DummyStepHandler.getInstance();
+    switchesHandler = new SwitchingFunctionsHandler();
+  }
+
+  /** Get the name of the method.
+   * @return name of the method
+   */
+  public abstract String getName();
+
+  /** Set the step handler for this integrator.
+   * The handler will be called by the integrator for each accepted
+   * step.
+   * @param handler handler for the accepted steps
+   */
+  public void setStepHandler (StepHandler handler) {
+    this.handler = handler;
+  }
+
+  /** Get the step handler for this integrator.
+   * @return the step handler for this integrator
+   */
+  public StepHandler getStepHandler() {
+    return handler;
+  }
+
+  /** Add a switching function to the integrator.
+   * @param function switching function
+   * @param maxCheckInterval maximal time interval between switching
+   * function checks (this interval prevents missing sign changes in
+   * case the integration steps becomes very large)
+   * @param convergence convergence threshold in the event time search
+   */
+  public void addSwitchingFunction(SwitchingFunction function,
+                                   double maxCheckInterval,
+                                   double convergence) {
+    switchesHandler.add(function, maxCheckInterval, convergence);
+  }
+
+  public void integrate(FirstOrderDifferentialEquations equations,
+                        double t0, double[] y0,
+                        double t, double[] y)
+  throws DerivativeException, IntegratorException {
+
+    // sanity check
+    if (equations.getDimension() != y0.length) {
+      throw new IntegratorException("dimensions mismatch: ODE problem has dimension {0},"
+                                    + " state vector has dimension {1}",
+                                    new String[] {
+                                      Integer.toString(equations.getDimension()),
+                                      Integer.toString(y0.length)
+                                    });
+    }
+    if (Math.abs(t - t0) <= 1.0e-12 * Math.max(Math.abs(t0), Math.abs(t))) {
+      throw new IntegratorException("too small integration interval: length = {0}",
+                                    new String[] {
+                                      Double.toString(Math.abs(t - t0))
+                                    });
+    }
+    
+    boolean forward = (t > t0);
+
+    // create some internal working arrays
+    int stages = c.length + 1;
+    if (y != y0) {
+      System.arraycopy(y0, 0, y, 0, y0.length);
+    }
+    double[][] yDotK = new double[stages][];
+    for (int i = 0; i < stages; ++i) {
+      yDotK [i] = new double[y0.length];
+    }
+    double[] yTmp = new double[y0.length];
+
+    // set up an interpolator sharing the integrator arrays
+    AbstractStepInterpolator interpolator;
+    if (handler.requiresDenseOutput() || (! switchesHandler.isEmpty())) {
+      RungeKuttaStepInterpolator rki = (RungeKuttaStepInterpolator) prototype.clone();
+      rki.reinitialize(equations, yTmp, yDotK, forward);
+      interpolator = rki;
+    } else {
+      interpolator = new DummyStepInterpolator(yTmp, forward);
+    }
+    interpolator.storeTime(t0);
+
+    // recompute the step
+    double  currentT  = t0;
+    long    nbStep    = Math.max(1l, Math.abs(Math.round((t - t0) / step)));
+    double  h         = (t - t0) / nbStep;
+    boolean firstTime = true;
+    boolean lastStep  = false;
+    handler.reset();
+    for (long i = 0; ! lastStep; ++i) {
+
+      interpolator.shift();
+
+      boolean needUpdate = false;
+      for (boolean loop = true; loop;) {
+
+        if (firstTime || !fsal) {
+          // first stage
+          equations.computeDerivatives(currentT, y, yDotK[0]);
+          firstTime = false;
+        }
+
+        // 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(currentT + 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];
+          }
+          yTmp[j] = y[j] + h * sum;
+        }
+
+        // Switching functions handling
+        interpolator.storeTime(currentT + h);
+        if (switchesHandler.evaluateStep(interpolator)) {
+          needUpdate = true;
+          h = switchesHandler.getEventTime() - currentT;
+        } else {
+          loop = false;
+        }
+
+      }
+
+      // the step has been accepted
+      currentT += h;
+      System.arraycopy(yTmp, 0, y, 0, y0.length);
+      switchesHandler.stepAccepted(currentT, y);
+      if (switchesHandler.stop()) {
+        lastStep = true;
+      } else {
+        lastStep = (i == (nbStep - 1));
+      }
+
+      // provide the step data to the step handler
+      interpolator.storeTime(currentT);
+      handler.handleStep(interpolator, lastStep);
+
+      if (fsal) {
+        // save the last evaluation for the next step
+        System.arraycopy(yDotK[stages - 1], 0, yDotK[0], 0, y0.length);
+      }
+
+      if (switchesHandler.reset(currentT, y) && ! lastStep) {
+        // some switching function has triggered changes that
+        // invalidate the derivatives, we need to recompute them
+        equations.computeDerivatives(currentT, y, yDotK[0]);
+      }
+
+      if (needUpdate) {
+        // a switching function has changed the step
+        // we need to recompute stepsize
+        nbStep = Math.max(1l, Math.abs(Math.round((t - currentT) / step)));
+        h = (t - currentT) / nbStep;
+        i = -1;
+      }
+
+    }
+
+  }
+
+  /** Indicator for <i>fsal</i> methods. */
+  private boolean fsal;
+
+  /** Time steps from Butcher array (without the first zero). */
+  private double[] c;
+
+  /** Internal weights from Butcher array (without the first empty row). */
+  private double[][] a;
+
+  /** External weights for the high order method from Butcher array. */
+  private double[] b;
+
+  /** Prototype of the step interpolator. */
+  private RungeKuttaStepInterpolator prototype;
+                                         
+  /** Integration step. */
+  private double step;
+
+  /** Step handler. */
+  private StepHandler handler;
+
+  /** Switching functions handler. */
+  protected SwitchingFunctionsHandler switchesHandler;
+
+}

Propchange: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/RungeKuttaIntegrator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/RungeKuttaStepInterpolator.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/RungeKuttaStepInterpolator.java?view=auto&rev=512066
==============================================================================
--- jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/RungeKuttaStepInterpolator.java (added)
+++ jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/RungeKuttaStepInterpolator.java Mon Feb 26 15:12:40 2007
@@ -0,0 +1,183 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF 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.apache.commons.math.ode;
+
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.IOException;
+
+/** This class represents an interpolator over the last step during an
+ * ODE integration for Runge-Kutta and Runge-Kutta-Fehlberg
+ * integrators.
+ *
+ * @see RungeKuttaIntegrator
+ * @see RungeKuttaFehlbergIntegrator
+ *
+ * @version $Id: RungeKuttaStepInterpolator.java 1705 2006-09-17 19:57:39Z luc $
+ * @author L. Maisonobe
+ *
+ */
+
+abstract class RungeKuttaStepInterpolator
+  extends AbstractStepInterpolator {
+
+  /** Simple constructor.
+   * This constructor builds an instance that is not usable yet, the
+   * {@link #reinitialize} method should be called before using the
+   * instance in order to initialize the internal arrays. This
+   * constructor is used only in order to delay the initialization in
+   * some cases. The {@link RungeKuttaIntegrator} and {@link
+   * RungeKuttaFehlbergIntegrator} classes uses the prototyping design
+   * pattern to create the step interpolators by cloning an
+   * uninitialized model and latter initializing the copy.
+   */
+  protected RungeKuttaStepInterpolator() {
+    super();
+    yDotK     = null;
+    equations = null;
+  }
+
+  /** Copy constructor.
+
+  * <p>The copied interpolator should have been finalized before the
+  * copy, otherwise the copy will not be able to perform correctly any
+  * interpolation and will throw a {@link NullPointerException}
+  * later. Since we don't want this constructor to throw the
+  * exceptions finalization may involve and since we don't want this
+  * method to modify the state of the copied interpolator,
+  * finalization is <strong>not</strong> done automatically, it
+  * remains under user control.</p>
+
+  * <p>The copy is a deep copy: its arrays are separated from the
+  * original arrays of the instance.</p>
+
+  * @param interpolator interpolator to copy from.
+
+  */
+  public RungeKuttaStepInterpolator(RungeKuttaStepInterpolator interpolator) {
+
+    super(interpolator);
+
+    if (interpolator.currentState != null) {
+      int dimension = currentState.length;
+
+      yDotK = new double[interpolator.yDotK.length][];
+      for (int k = 0; k < interpolator.yDotK.length; ++k) {
+        yDotK[k] = new double[dimension];
+        System.arraycopy(interpolator.yDotK[k], 0,
+                         yDotK[k], 0, dimension);
+      }
+
+    } else {
+      yDotK = null;
+    }
+
+    // we cannot keep any reference to the equations in the copy
+    // the interpolator should have been finalized before
+    equations = null;
+
+  }
+
+  /** Reinitialize the instance
+   * <p>Some Runge-Kutta integrators need fewer functions evaluations
+   * than their counterpart step interpolators. So the interpolator
+   * should perform the last evaluations they need by themselves. The
+   * {@link RungeKuttaIntegrator RungeKuttaIntegrator} and {@link
+   * RungeKuttaFehlbergIntegrator RungeKuttaFehlbergIntegrator}
+   * abstract classes call this method in order to let the step
+   * interpolator perform the evaluations it needs. These evaluations
+   * will be performed during the call to <code>doFinalize</code> if
+   * any, i.e. only if the step handler either calls the {@link
+   * AbstractStepInterpolator#finalizeStep finalizeStep} method or the
+   * {@link AbstractStepInterpolator#getInterpolatedState
+   * getInterpolatedState} method (for an interpolator which needs a
+   * finalization) or if it clones the step interpolator.</p>
+   * @param equations set of differential equations being integrated
+   * @param y reference to the integrator array holding the state at
+   * the end of the step
+   * @param yDotK reference to the integrator array holding all the
+   * intermediate slopes
+   * @param forward integration direction indicator
+   */
+  public void reinitialize(FirstOrderDifferentialEquations equations,
+                           double[] y, double[][] yDotK, boolean forward) {
+    reinitialize(y, forward);
+    this.yDotK = yDotK;
+    this.equations = equations;
+  }
+
+  /** Save the state of the instance.
+   * @param out stream where to save the state
+   * @exception IOException in case of write error
+   */
+  public void writeExternal(ObjectOutput out)
+    throws IOException {
+
+    // save the state of the base class
+    writeBaseExternal(out);
+
+    // save the local attributes
+    out.writeInt(yDotK.length);
+    for (int k = 0; k < yDotK.length; ++k) {
+      for (int i = 0; i < currentState.length; ++i) {
+        out.writeDouble(yDotK[k][i]);
+      }
+    }
+
+    // we do not save any reference to the equations
+
+  }
+
+  /** Read the state of the instance.
+   * @param in stream where to read the state from
+   * @exception IOException in case of read error
+   */
+  public void readExternal(ObjectInput in)
+    throws IOException {
+
+    // read the base class 
+    double t = readBaseExternal(in);
+
+    // read the local attributes
+    int kMax = in.readInt();
+    yDotK = new double[kMax][];
+    for (int k = 0; k < kMax; ++k) {
+      yDotK[k] = new double[currentState.length];
+      for (int i = 0; i < currentState.length; ++i) {
+        yDotK[k][i] = in.readDouble();
+      }
+    }
+
+    equations = null;
+
+    try {
+      // we can now set the interpolated time and state
+      setInterpolatedTime(t);
+    } catch (DerivativeException e) {
+      throw new IOException(e.getMessage());
+    }
+
+  }
+
+  /** Slopes at the intermediate points */
+  protected double[][] yDotK;
+
+  /** Reference to the differential equations beeing integrated. */
+  protected FirstOrderDifferentialEquations equations;
+
+}

Propchange: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/RungeKuttaStepInterpolator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SecondOrderDifferentialEquations.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SecondOrderDifferentialEquations.java?view=auto&rev=512066
==============================================================================
--- jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SecondOrderDifferentialEquations.java (added)
+++ jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SecondOrderDifferentialEquations.java Mon Feb 26 15:12:40 2007
@@ -0,0 +1,71 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF 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.apache.commons.math.ode;
+
+/** This interface represents a second order differential equations set.
+
+ * <p>This interface should be implemented by all real second order
+ * differential equation problems before they can be handled by the
+ * integrators {@link SecondOrderIntegrator#integrate} method.</p>
+
+ * <p>A second order differential equations problem, as seen by an
+ * integrator is the second time derivative <code>d2Y/dt^2</code> of a
+ * state vector <code>Y</code>, both being one dimensional
+ * arrays. From the integrator point of view, this derivative depends
+ * only on the current time <code>t</code>, on the state vector
+ * <code>Y</code> and on the first time derivative of the state
+ * vector.</p>
+
+ * <p>For real problems, the derivative depends also on parameters
+ * that do not belong to the state vector (dynamical model constants
+ * for example). These constants are completely outside of the scope
+ * of this interface, the classes that implement it are allowed to
+ * handle them as they want.</p>
+
+ * @see SecondOrderIntegrator
+ * @see FirstOrderConverter
+ * @see FirstOrderDifferentialEquations
+ * @see org.spaceroots.mantissa.utilities.ArraySliceMappable
+
+ * @version $Id: SecondOrderDifferentialEquations.java 1705 2006-09-17 19:57:39Z luc $
+ * @author L. Maisonobe
+
+ */
+
+public interface SecondOrderDifferentialEquations {
+
+  /** Get the dimension of the problem.
+   * @return dimension of the problem
+   */
+  public int getDimension();
+    
+  /** Get the current time derivative of the state vector.
+   * @param t current value of the independant <I>time</I> variable
+   * @param y array containing the current value of the state vector
+   * @param yDot array containing the current value of the first derivative
+   * of the state vector
+   * @param yDDot placeholder array where to put the second time derivative
+   * of the state vector
+   * @throws DerivativeException this exception is propagated to the caller if the
+   * underlying user function triggers one
+   */
+  public void computeSecondDerivatives(double t, double[] y, double[] yDot,
+                                       double[] yDDot)
+  throws DerivativeException;
+
+}

Propchange: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SecondOrderDifferentialEquations.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SecondOrderIntegrator.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SecondOrderIntegrator.java?view=auto&rev=512066
==============================================================================
--- jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SecondOrderIntegrator.java (added)
+++ jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SecondOrderIntegrator.java Mon Feb 26 15:12:40 2007
@@ -0,0 +1,76 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF 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.apache.commons.math.ode;
+
+/** This interface represents a second order integrator for
+ * differential equations.
+
+ * <p>The classes which are devoted to solve second order differential
+ * equations should implement this interface. The problems which can
+ * be handled should implement the {@link
+ * SecondOrderDifferentialEquations} interface.</p>
+
+ * @see SecondOrderDifferentialEquations
+
+ * @version $Id: SecondOrderIntegrator.java 1705 2006-09-17 19:57:39Z luc $
+ * @author L. Maisonobe
+
+ */
+
+public interface SecondOrderIntegrator {
+
+  /** Get the name of the method.
+   * @return name of the method
+   */
+  public String getName();
+
+  /** Set the step handler for this integrator.
+   * The handler will be called by the integrator for each accepted
+   * step.
+   * @param handler handler for the accepted steps
+   */
+  public void setStepHandler (StepHandler handler);
+
+  /** Get the step handler for this integrator.
+   * @return the step handler for this integrator
+   */
+  public StepHandler getStepHandler();
+
+  /** Integrate the differential equations up to the given time
+   * @param equations differential equations to integrate
+   * @param t0 initial time
+   * @param y0 initial value of the state vector at t0
+   * @param yDot0 initial value of the first derivative of the state
+   * vector at t0
+   * @param t target time for the integration
+   * (can be set to a value smaller thant <code>t0</code> for backward integration)
+   * @param y placeholder where to put the state vector at each
+   * successful step (and hence at the end of integration), can be the
+   * same object as y0
+   * @param yDot placeholder where to put the first derivative of
+   * the state vector at time t, can be the same object as yDot0
+   * @throws IntegratorException if the integrator cannot perform integration
+   * @throws DerivativeException this exception is propagated to the caller if the
+   * underlying user function triggers one
+   */
+  public void integrate(SecondOrderDifferentialEquations equations,
+                        double t0, double[] y0, double[] yDot0,
+                        double t, double[] y, double[] yDot)
+  throws DerivativeException, IntegratorException;
+
+}

Propchange: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SecondOrderIntegrator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/StepHandler.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/StepHandler.java?view=auto&rev=512066
==============================================================================
--- jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/StepHandler.java (added)
+++ jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/StepHandler.java Mon Feb 26 15:12:40 2007
@@ -0,0 +1,79 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF 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.apache.commons.math.ode;
+
+/**
+ * This interface represents a handler that should be called after
+ * each successful step.
+
+ * <p>The ODE integrators compute the evolution of the state vector at
+ * some grid points that depend on their own internal algorithm. Once
+ * they have found a new grid point (possibly after having computed
+ * several evaluation of the derivative at intermediate points), they
+ * provide it to objects implementing this interface. These objects
+ * typically either ignore the intermediate steps and wait for the
+ * last one, store the points in an ephemeris, or forward them to
+ * specialized processing or output methods.</p>
+
+ * @see FirstOrderIntegrator
+ * @see SecondOrderIntegrator
+ * @see StepInterpolator
+
+ * @version $Id: StepHandler.java 1705 2006-09-17 19:57:39Z luc $
+ * @author L. Maisonobe
+
+ */
+
+public interface StepHandler {
+
+  /** Determines whether this handler needs dense output.
+   * <p>This method allows the integrator to avoid performing extra
+   * computation if the handler does not need dense output. If this
+   * method returns false, the integrator will call the {@link
+   * #handleStep} method with a {@link DummyStepInterpolator} rather
+   * than a custom interpolator.</p>
+   * @return true if the handler needs dense output
+   */
+  public boolean requiresDenseOutput();
+
+  /** Reset the step handler.
+   * Initialize the internal data as required before the first step is
+   * handled.
+   */
+  public void reset();
+
+  /**
+   * Handle the last accepted step
+   * @param interpolator interpolator for the last accepted step. For
+   * efficiency purposes, the various integrators reuse the same
+   * object on each call, so if the instance wants to keep it across
+   * all calls (for example to provide at the end of the integration a
+   * continuous model valid throughout the integration range, as the
+   * {@link ContinuousOutputModel ContinuousOutputModel} class does),
+   * it should build a local copy using the clone method of the
+   * interpolator and store this copy. Keeping only a reference to the
+   * interpolator and reusing it will result in unpredictable
+   * behaviour (potentially crashing the application).
+   * @param isLast true if the step is the last one
+   * @throws DerivativeException this exception is propagated to the
+   * caller if the underlying user function triggers one
+   */
+  public void handleStep(StepInterpolator interpolator, boolean isLast)
+    throws DerivativeException;
+    
+}

Propchange: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/StepHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/StepInterpolator.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/StepInterpolator.java?view=auto&rev=512066
==============================================================================
--- jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/StepInterpolator.java (added)
+++ jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/StepInterpolator.java Mon Feb 26 15:12:40 2007
@@ -0,0 +1,96 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF 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.apache.commons.math.ode;
+
+import java.io.Externalizable;
+
+/** This interface represents an interpolator over the last step
+ * during an ODE integration.
+ *
+ * <p>The various ODE integrators provide objects implementing this
+ * interface to the step handlers. These objects are often custom
+ * objects tightly bound to the integrator internal algorithms. The
+ * handlers can use these objects to retrieve the state vector at
+ * intermediate times between the previous and the current grid points
+ * (this feature is often called dense output).</p>
+ *
+ * @see FirstOrderIntegrator
+ * @see SecondOrderIntegrator
+ * @see StepHandler
+ *
+ * @version $Id: StepInterpolator.java 1705 2006-09-17 19:57:39Z luc $
+ * @author L. Maisonobe
+ *
+ */
+
+public interface StepInterpolator
+  extends Externalizable {
+
+  /**
+   * Get the previous grid point time.
+   * @return previous grid point time
+   */
+  public double getPreviousTime();
+    
+  /**
+   * Get the current grid point time.
+   * @return current grid point time
+   */
+  public double getCurrentTime();
+    
+  /**
+   * Get the time of the interpolated point.
+   * If {@link #setInterpolatedTime} has not been called, it returns
+   * the current grid point time.
+   * @return interpolation point time
+   */
+  public double getInterpolatedTime();
+    
+  /**
+   * Set the time of the interpolated point.
+   * <p>Setting the time outside of the current step is now allowed
+   * (it was not allowed up to version 5.4 of Mantissa), but should be
+   * used with care since the accuracy of the interpolator will
+   * probably be very poor far from this step. This allowance has been
+   * added to simplify implementation of search algorithms near the
+   * step endpoints.</p>
+   * @param time time of the interpolated point
+   * @throws DerivativeException if this call induces an automatic
+   * step finalization that throws one
+   */
+  public void setInterpolatedTime(double time)
+    throws DerivativeException;
+
+  /**
+   * Get the state vector of the interpolated point.
+   * @return state vector at time {@link #getInterpolatedTime}
+   */
+  public double[] getInterpolatedState();
+
+  /** Check if the natural integration direction is forward.
+   * <p>This method provides the integration direction as specified by
+   * the integrator itself, it avoid some nasty problems in
+   * degenerated cases like null steps due to cancellation at step
+   * initialization, step control or switching function
+   * triggering.</p>
+   * @return true if the integration variable (time) increases during
+   * integration
+   */
+  public boolean isForward();
+
+}

Propchange: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/StepInterpolator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/StepNormalizer.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/StepNormalizer.java?view=auto&rev=512066
==============================================================================
--- jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/StepNormalizer.java (added)
+++ jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/StepNormalizer.java Mon Feb 26 15:12:40 2007
@@ -0,0 +1,158 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF 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.apache.commons.math.ode;
+
+/**
+ * This class wraps an object implementing {@link FixedStepHandler}
+ * into a {@link StepHandler}.
+
+ * <p>This wrapper allows to use fixed step handlers with general
+ * integrators which cannot guaranty their integration steps will
+ * remain constant and therefore only accept general step
+ * handlers.</p>
+
+ * <p>The stepsize used is selected at construction time. The {@link
+ * FixedStepHandler#handleStep handleStep} method of the underlying
+ * {@link FixedStepHandler} object is called at the beginning time of
+ * the integration t0 and also at times t0+h, t0+2h, ... If the
+ * integration range is an integer multiple of the stepsize, then the
+ * last point handled will be the endpoint of the integration tend, if
+ * not, the last point will belong to the interval [tend - h ;
+ * tend].</p>
+
+ * <p>There is no constraint on the integrator, it can use any
+ * timestep it needs (time steps longer or shorter than the fixed time
+ * step and non-integer ratios are all allowed).</p>
+
+ * @see StepHandler
+ * @see FixedStepHandler
+
+ * @version $Id: StepNormalizer.java 1705 2006-09-17 19:57:39Z luc $
+ * @author L. Maisonobe
+
+ */
+
+public class StepNormalizer
+  implements StepHandler {
+
+  /** Simple constructor.
+   * @param h fixed time step (sign is not used)
+   * @param handler fixed time step handler to wrap
+   */
+  public StepNormalizer(double h, FixedStepHandler handler) {
+    this.h       = Math.abs(h);
+    this.handler = handler;
+    reset();
+  }
+
+  /** Determines whether this handler needs dense output.
+   * This handler needs dense output in order to provide data at
+   * regularly spaced steps regardless of the steps the integrator
+   * uses, so this method always returns true.
+   * @return always true
+   */
+  public boolean requiresDenseOutput() {
+    return true;
+  }
+
+  /** Reset the step handler.
+   * Initialize the internal data as required before the first step is
+   * handled.
+   */
+  public void reset() {
+    lastTime  = Double.NaN;
+    lastState = null;
+    forward   = true;
+  }
+
+  /**
+   * Handle the last accepted step
+   * @param interpolator interpolator for the last accepted step. For
+   * efficiency purposes, the various integrators reuse the same
+   * object on each call, so if the instance wants to keep it across
+   * all calls (for example to provide at the end of the integration a
+   * continuous model valid throughout the integration range), it
+   * should build a local copy using the clone method and store this
+   * copy.
+   * @param isLast true if the step is the last one
+   * @throws DerivativeException this exception is propagated to the
+   * caller if the underlying user function triggers one
+   */
+  public void handleStep(StepInterpolator interpolator, boolean isLast)
+    throws DerivativeException {
+
+    double nextTime;
+
+    if (lastState == null) {
+
+      lastTime = interpolator.getPreviousTime();
+      interpolator.setInterpolatedTime(lastTime);
+
+      double[] state = interpolator.getInterpolatedState();
+      lastState = (double[]) state.clone();
+
+      // take the integration direction into account
+      forward = (interpolator.getCurrentTime() >= lastTime);
+      if (! forward) {
+        h = -h;
+      }
+
+    }
+
+    nextTime = lastTime + h;
+    boolean nextInStep = forward ^ (nextTime > interpolator.getCurrentTime());
+    while (nextInStep) {
+
+      // output the stored previous step
+      handler.handleStep(lastTime, lastState, false);
+
+      // store the next step
+      lastTime = nextTime;
+      interpolator.setInterpolatedTime(lastTime);
+      System.arraycopy(interpolator.getInterpolatedState(), 0,
+                       lastState, 0, lastState.length);
+
+      nextTime  += h;
+      nextInStep = forward ^ (nextTime > interpolator.getCurrentTime());
+
+    }
+
+    if (isLast) {
+      // there will be no more steps,
+      // the stored one should be flagged as being the last
+      handler.handleStep(lastTime, lastState, true);
+    }
+
+  }
+
+  /** Fixed time step. */
+  private double h;
+
+  /** Underlying step handler. */
+  private FixedStepHandler handler;
+
+  /** Last step time. */
+  private double lastTime;
+
+  /** Last State vector. */
+  private double[] lastState;
+
+  /** Integration direction indicator. */
+  private boolean forward;
+
+}

Propchange: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/StepNormalizer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SwitchState.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SwitchState.java?view=auto&rev=512066
==============================================================================
--- jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SwitchState.java (added)
+++ jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SwitchState.java Mon Feb 26 15:12:40 2007
@@ -0,0 +1,267 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF 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.apache.commons.math.ode;
+
+import java.io.Serializable;
+
+import org.apache.commons.math.ConvergenceException;
+import org.apache.commons.math.FunctionEvaluationException;
+import org.apache.commons.math.analysis.BrentSolver;
+import org.apache.commons.math.analysis.UnivariateRealFunction;
+import org.apache.commons.math.analysis.UnivariateRealSolver;
+
+/** This class handles the state for one {@link SwitchingFunction
+ * switching function} during integration steps.
+ *
+ * <p>Each time the integrator proposes a step, the switching function
+ * should be checked. This class handles the state of one function
+ * during one integration step, with references to the state at the
+ * end of the preceding step. This information is used to determine if
+ * the function should trigger an event or not during the proposed
+ * step (and hence the step should be reduced to ensure the event
+ * occurs at a bound rather than inside the step).</p>
+ *
+ * @version $Id: SwitchState.java 1705 2006-09-17 19:57:39Z luc $
+ * @author L. Maisonobe
+ *
+ */
+class SwitchState implements Serializable {
+
+  /** Serializable version identifier. */
+  private static final long serialVersionUID = 3256541562455482289L;
+
+  /** Switching function. */
+  private SwitchingFunction function;
+
+  /** Maximal time interval between switching function checks. */
+  private double maxCheckInterval;
+
+  /** Convergence threshold for event localisation. */
+  private double convergence;
+
+  /** Time at the beginning of the step. */
+  private double t0;
+
+  /** Value of the switching function at the beginning of the step. */
+  private double g0;
+
+  /** Simulated sign of g0 (we cheat when crossing events). */
+  private boolean g0Positive;
+
+  /** Indicator of event expected during the step. */
+  private boolean pendingEvent;
+
+  /** Occurrence time of the pending event. */
+  private double pendingEventTime;
+
+  /** Occurrence time of the previous event. */
+  private double previousEventTime;
+
+  /** Variation direction around pending event.
+   *  (this is considered with respect to the integration direction)
+   */
+  private boolean increasing;
+
+  /** Next action indicator. */
+  private int nextAction;
+
+  /** Simple constructor.
+   * @param function switching function
+   * @param maxCheckInterval maximal time interval between switching
+   * function checks (this interval prevents missing sign changes in
+   * case the integration steps becomes very large)
+   * @param convergence convergence threshold in the event time search
+   */
+  public SwitchState(SwitchingFunction function,
+                     double maxCheckInterval, double convergence) {
+    this.function         = function;
+    this.maxCheckInterval = maxCheckInterval;
+    this.convergence      = Math.abs(convergence);
+
+    // some dummy values ...
+    t0                = Double.NaN;
+    g0                = Double.NaN;
+    g0Positive        = true;
+    pendingEvent      = false;
+    pendingEventTime  = Double.NaN;
+    previousEventTime = Double.NaN;
+    increasing        = true;
+    nextAction        = SwitchingFunction.CONTINUE;
+
+  }
+
+  /** Reinitialize the beginning of the step.
+   * @param t0 value of the independant <i>time</i> variable at the
+   * beginning of the step
+   * @param y0 array containing the current value of the state vector
+   * at the beginning of the step
+   */
+  public void reinitializeBegin(double t0, double[] y0) {
+    this.t0 = t0;
+    g0 = function.g(t0, y0);
+    g0Positive = (g0 >= 0);
+  }
+
+  /** Evaluate the impact of the proposed step on the switching function.
+   * @param interpolator step interpolator for the proposed step
+   * @return true if the switching function triggers an event before
+   * the end of the proposed step (this implies the step should be
+   * rejected)
+   */
+  public boolean evaluateStep(final StepInterpolator interpolator) {
+
+    try {
+
+      double t1 = interpolator.getCurrentTime();
+      int    n  = Math.max(1, (int) Math.ceil(Math.abs(t1 - t0) / maxCheckInterval));
+      double h  = (t1 - t0) / n;
+
+      double ta = t0;
+      double ga = g0;
+      double tb = t0 + ((t1 > t0) ? convergence : -convergence);
+      for (int i = 0; i < n; ++i) {
+
+        // evaluate function value at the end of the substep
+        tb += h;
+        interpolator.setInterpolatedTime(tb);
+        double gb = function.g(tb, interpolator.getInterpolatedState());
+
+        // check events occurrence
+        if (g0Positive ^ (gb >= 0)) {
+          // there is a sign change: an event is expected during this step
+
+          // variation direction, with respect to the integration direction
+          increasing = (gb >= ga);
+
+          try {
+              UnivariateRealSolver solver = new BrentSolver(new UnivariateRealFunction() {
+                  public double value(double t) throws FunctionEvaluationException {
+                      try {
+                          interpolator.setInterpolatedTime(t);
+                          return function.g(t, interpolator.getInterpolatedState());
+                      } catch (DerivativeException e) {
+                          throw new FunctionEvaluationException(t, e);
+                      }
+                  }
+              });
+              solver.setAbsoluteAccuracy(convergence);
+              solver.setMaximalIterationCount(1000);
+              double root = solver.solve(ta, tb);
+              if (Double.isNaN(previousEventTime) || (Math.abs(previousEventTime - root) > convergence)) {
+                  pendingEventTime = root;
+                  if (pendingEvent && (Math.abs(t1 - pendingEventTime) <= convergence)) {
+                      // we were already waiting for this event which was
+                      // found during a previous call for a step that was
+                      // rejected, this step must now be accepted since it
+                      // properly ends exactly at the event occurrence
+                      return false;
+                  }
+                  // either we were not waiting for the event or it has
+                  // moved in such a way the step cannot be accepted
+                  pendingEvent = true;
+                  return true;
+              }
+          } catch (ConvergenceException ce) {
+              throw new RuntimeException("internal error");
+          }
+
+        } else {
+          // no sign change: there is no event for now
+          ta = tb;
+          ga = gb;
+        }
+
+      }
+
+      // no event during the whole step
+      pendingEvent     = false;
+      pendingEventTime = Double.NaN;
+      return false;
+
+    } catch (DerivativeException e) {
+      throw new RuntimeException("unexpected exception: " + e.getMessage());
+    } catch (FunctionEvaluationException e) {
+      throw new RuntimeException("unexpected exception: " + e.getMessage());
+    }
+
+  }
+
+  /** Get the occurrence time of the event triggered in the current
+   * step.
+   * @return occurrence time of the event triggered in the current
+   * step.
+   */
+  public double getEventTime() {
+    return pendingEventTime;
+  }
+
+  /** Acknowledge the fact the step has been accepted by the integrator.
+   * @param t value of the independant <i>time</i> variable at the
+   * end of the step
+   * @param y array containing the current value of the state vector
+   * at the end of the step
+   */
+  public void stepAccepted(double t, double[] y) {
+
+    t0 = t;
+    g0 = function.g(t, y);
+
+    if (pendingEvent) {
+      // force the sign to its value "just after the event"
+      previousEventTime = t;
+      g0Positive        = increasing;
+      nextAction        = function.eventOccurred(t, y);
+    } else {
+      g0Positive = (g0 >= 0);
+      nextAction = SwitchingFunction.CONTINUE;
+    }
+  }
+
+  /** Check if the integration should be stopped at the end of the
+   * current step.
+   * @return true if the integration should be stopped
+   */
+  public boolean stop() {
+    return nextAction == SwitchingFunction.STOP;
+  }
+
+  /** Let the switching function reset the state if it wants.
+   * @param t value of the independant <i>time</i> variable at the
+   * beginning of the next step
+   * @param y array were to put the desired state vector at the beginning
+   * of the next step
+   * @return true if the integrator should reset the derivatives too
+   */
+  public boolean reset(double t, double[] y) {
+
+    if (! pendingEvent) {
+      return false;
+    }
+
+    if (nextAction == SwitchingFunction.RESET_STATE) {
+      function.resetState(t, y);
+    }
+    pendingEvent      = false;
+    pendingEventTime  = Double.NaN;
+
+    return (nextAction == SwitchingFunction.RESET_STATE)
+        || (nextAction == SwitchingFunction.RESET_DERIVATIVES);
+
+  }
+
+}

Propchange: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SwitchState.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SwitchingFunction.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SwitchingFunction.java?view=auto&rev=512066
==============================================================================
--- jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SwitchingFunction.java (added)
+++ jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SwitchingFunction.java Mon Feb 26 15:12:40 2007
@@ -0,0 +1,151 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF 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.apache.commons.math.ode;
+
+import java.io.Serializable;
+
+/** This interface represents a switching function.
+ *
+ * <p>A switching function allows to handle discrete events in
+ * integration problems. These events occur for example when the
+ * integration process should be stopped as some value is reached
+ * (G-stop facility), or when the derivatives have
+ * discontinuities, or simply when the user wants to monitor some
+ * states boundaries crossings. These events are traditionally defined
+ * as occurring when a <code>g</code> function sign changes, hence
+ * the name <em>switching functions</em>.</p>
+ *
+ * <p>Since events are only problem-dependent and are triggered by the
+ * independant <i>time</i> variable and the state vector, they can
+ * occur at virtually any time, unknown in advance. The integrators will
+ * take care to avoid sign changes inside the steps, they will reduce
+ * the step size when such an event is detected in order to put this
+ * event exactly at the end of the current step. This guarantees that
+ * step interpolation (which always has a one step scope) is relevant
+ * even in presence of discontinuities. This is independent from the
+ * stepsize control provided by integrators that monitor the local
+ * error (this feature is available on all integrators, including
+ * fixed step ones).</p>
+ *
+ * @version $Id: SwitchingFunction.java 1705 2006-09-17 19:57:39Z luc $
+ * @author L. Maisonobe
+ *
+ */
+
+public interface SwitchingFunction extends Serializable {
+
+  /** Stop indicator.
+   * <p>This value should be used as the return value of the {@link
+   * #eventOccurred eventOccurred} method when the integration should be
+   * stopped after the event ending the current step.</p>
+   */
+  public static final int STOP = 0;
+
+  /** Reset state indicator.
+   * <p>This value should be used as the return value of the {@link
+   * #eventOccurred eventOccurred} method when the integration should
+   * go on after the event ending the current step, with a new state
+   * vector (which will be retrieved thanks to the {@link #resetState
+   * resetState} method).</p>
+   */
+  public static final int RESET_STATE = 1;
+
+  /** Reset derivatives indicator.
+   * <p>This value should be used as the return value of the {@link
+   * #eventOccurred eventOccurred} method when the integration should
+   * go on after the event ending the current step, with a new derivatives
+   * vector (which will be retrieved thanks to the {@link
+   * FirstOrderDifferentialEquations#computeDerivatives} method).</p>
+   */
+  public static final int RESET_DERIVATIVES = 2;
+
+  /** Continue indicator.
+   * <p>This value should be used as the return value of the {@link
+   * #eventOccurred eventOccurred} method when the integration should go
+   * on after the event ending the current step.</p>
+   */
+  public static final int CONTINUE = 3;
+
+  /** Compute the value of the switching function.
+
+   * <p>Discrete events are generated when the sign of this function
+   * changes, the integrator will take care to change the stepsize in
+   * such a way these events occur exactly at step boundaries. This
+   * function must be continuous (at least in its roots neighborhood),
+   * as the integrator will need to find its roots to locate the events.</p>
+
+   * @param t current value of the independant <i>time</i> variable
+   * @param y array containing the current value of the state vector
+   * @return value of the g function
+   */
+  public double g(double t, double[] y);
+
+  /** Handle an event and choose what to do next.
+
+   * <p>This method is called when the integrator has accepted a step
+   * ending exactly on a sign change of the function, just before the
+   * step handler itself is called. It allows the user to update his
+   * internal data to acknowledge the fact the event has been handled
+   * (for example setting a flag in the {@link
+   * FirstOrderDifferentialEquations differential equations} to switch
+   * the derivatives computation in case of discontinuity), or to
+   * direct the integrator to either stop or continue integration,
+   * possibly with a reset state or derivatives.</p>
+
+   * <ul>
+   *   <li>if {@link #STOP} is returned, the step handler will be called
+   *   with the <code>isLast</code> flag of the {@link
+   *   StepHandler#handleStep handleStep} method set to true and the
+   *   integration will be stopped,</li>
+   *   <li>if {@link #RESET_STATE} is returned, the {@link #resetState
+   *   resetState} method will be called once the step handler has
+   *   finished its task, and the integrator will also recompute the
+   *   derivatives,</li>
+   *   <li>if {@link #RESET_DERIVATIVES} is returned, the integrator
+   *   will recompute the derivatives,
+   *   <li>if {@link #CONTINUE} is returned, no specific action will
+   *   be taken (apart from having called this method) and integration
+   *   will continue.</li>
+   * </ul>
+
+   * @param t current value of the independant <i>time</i> variable
+   * @param y array containing the current value of the state vector
+   * @return indication of what the integrator should do next, this
+   * value must be one of {@link #STOP}, {@link #RESET_STATE},
+   * {@link #RESET_DERIVATIVES} or {@link #CONTINUE}
+   */
+  public int eventOccurred(double t, double[] y);
+  
+  /** Reset the state prior to continue the integration.
+
+   * <p>This method is called after the step handler has returned and
+   * before the next step is started, but only when {@link
+   * #eventOccurred} has itself returned the {@link #RESET_STATE}
+   * indicator. It allows the user to reset the state vector for the
+   * next step, without perturbing the step handler of the finishing
+   * step. If the {@link #eventOccurred} never returns the {@link
+   * #RESET_STATE} indicator, this function will never be called, and it is
+   * safe to leave its body empty.</p>
+
+   * @param t current value of the independant <i>time</i> variable
+   * @param y array containing the current value of the state vector
+   * the new state should be put in the same array
+   */
+  public void resetState(double t, double[] y);
+
+}

Propchange: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SwitchingFunction.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SwitchingFunctionsHandler.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SwitchingFunctionsHandler.java?view=auto&rev=512066
==============================================================================
--- jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SwitchingFunctionsHandler.java (added)
+++ jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SwitchingFunctionsHandler.java Mon Feb 26 15:12:40 2007
@@ -0,0 +1,190 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF 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.apache.commons.math.ode;
+
+import org.apache.commons.math.ode.DerivativeException;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/** This class handles several {@link SwitchingFunction switching
+ * functions} during integration.
+ *
+ * @see SwitchingFunction
+ *
+ * @version $Id: SwitchingFunctionsHandler.java 1705 2006-09-17 19:57:39Z luc $
+ * @author L. Maisonobe
+ *
+ */
+
+public class SwitchingFunctionsHandler {
+
+  /** Simple constructor.
+   * Create an empty handler
+   */
+  public SwitchingFunctionsHandler() {
+    functions   = new ArrayList();
+    first       = null;
+    initialized = false;
+  }
+
+  /** Add a switching function.
+   * @param function switching function
+   * @param maxCheckInterval maximal time interval between switching
+   * function checks (this interval prevents missing sign changes in
+   * case the integration steps becomes very large)
+   * @param convergence convergence threshold in the event time search
+   */
+  public void add(SwitchingFunction function,
+                  double maxCheckInterval, double convergence) {
+    functions.add(new SwitchState(function, maxCheckInterval, convergence));
+  }
+
+  /** Check if the handler does not have any condition.
+   * @return true if handler is empty
+   */
+  public boolean isEmpty() {
+    return functions.isEmpty();
+  }
+
+  /** Evaluate the impact of the proposed step on all handled
+   * switching functions.
+   * @param interpolator step interpolator for the proposed step
+   * @return true if at least one switching function triggers an event
+   * before the end of the proposed step (this implies the step should
+   * be rejected)
+   */
+  public boolean evaluateStep(StepInterpolator interpolator) {
+
+    try {
+
+      first = null;
+      if (functions.isEmpty()) {
+        // there is nothing to do, return now to avoid setting the
+        // interpolator time (and hence avoid unneeded calls to the
+        // user function due to interpolator finalization)
+        return false;
+      }
+
+      if (! initialized) {
+
+        // initialize the switching functions
+        double t0 = interpolator.getPreviousTime();
+        interpolator.setInterpolatedTime(t0);
+        double [] y = interpolator.getInterpolatedState();
+        for (Iterator iter = functions.iterator(); iter.hasNext();) {
+          ((SwitchState) iter.next()).reinitializeBegin(t0, y);
+        }
+
+        initialized = true;
+
+      }
+
+      // check events occurrence
+      for (Iterator iter = functions.iterator(); iter.hasNext();) {
+
+        SwitchState state = (SwitchState) iter.next();
+        if (state.evaluateStep(interpolator)) {
+          if (first == null) {
+            first = state;
+          } else {
+            if (interpolator.isForward()) {
+              if (state.getEventTime() < first.getEventTime()) {
+                first = state;
+              }
+            } else {
+              if (state.getEventTime() > first.getEventTime()) {
+                first = state;
+              }
+            }
+          }
+        }
+
+      }
+
+      return first != null;
+
+    } catch (DerivativeException e) {
+      throw new RuntimeException("unexpected exception: " + e.getMessage());
+    }
+
+  }
+
+  /** Get the occurrence time of the first event triggered in the
+   * last evaluated step.
+   * @return occurrence time of the first event triggered in the last
+   * evaluated step, or </code>Double.NaN</code> if no event is
+   * triggered
+   */
+  public double getEventTime() {
+    return (first == null) ? Double.NaN : first.getEventTime();
+  }
+
+  /** Inform the switching functions that the step has been accepted
+   * by the integrator.
+   * @param t value of the independant <i>time</i> variable at the
+   * end of the step
+   * @param y array containing the current value of the state vector
+   * at the end of the step
+   */
+  public void stepAccepted(double t, double[] y) {
+    for (Iterator iter = functions.iterator(); iter.hasNext();) {
+      ((SwitchState) iter.next()).stepAccepted(t, y);
+    }
+  }
+
+  /** Check if the integration should be stopped at the end of the
+   * current step.
+   * @return true if the integration should be stopped
+   */
+  public boolean stop() {
+    for (Iterator iter = functions.iterator(); iter.hasNext();) {
+      if (((SwitchState) iter.next()).stop()) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /** Let the switching functions reset the state if they want.
+   * @param t value of the independant <i>time</i> variable at the
+   * beginning of the next step
+   * @param y array were to put the desired state vector at the beginning
+   * of the next step
+   * @return true if the integrator should reset the derivatives too
+   */
+  public boolean reset(double t, double[] y) {
+    boolean resetDerivatives = false;
+    for (Iterator iter = functions.iterator(); iter.hasNext();) {
+      if (((SwitchState) iter.next()).reset(t, y)) {
+        resetDerivatives = true;
+      }
+    }
+    return resetDerivatives;
+  }
+
+  /** Switching functions. */
+  private ArrayList functions;
+
+  /** First active switching function. */
+  private SwitchState first;
+
+  /** Initialization indicator. */
+  private boolean initialized;
+
+}

Propchange: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/SwitchingFunctionsHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/ThreeEighthesIntegrator.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/ThreeEighthesIntegrator.java?view=auto&rev=512066
==============================================================================
--- jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/ThreeEighthesIntegrator.java (added)
+++ jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/ThreeEighthesIntegrator.java Mon Feb 26 15:12:40 2007
@@ -0,0 +1,80 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF 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.apache.commons.math.ode;
+
+/**
+ * This class implements the 3/8 fourth order Runge-Kutta
+ * integrator for Ordinary Differential Equations.
+
+ * <p>This method is an explicit Runge-Kutta method, its Butcher-array
+ * is the following one :
+ * <pre>
+ *    0  |  0    0    0    0
+ *   1/3 | 1/3   0    0    0
+ *   2/3 |-1/3   1    0    0
+ *    1  |  1   -1    1    0
+ *       |--------------------
+ *       | 1/8  3/8  3/8  1/8
+ * </pre>
+ * </p>
+
+ * @see EulerIntegrator
+ * @see ClassicalRungeKuttaIntegrator
+ * @see GillIntegrator
+ * @see MidpointIntegrator
+
+ * @version $Id: ThreeEighthesIntegrator.java 1705 2006-09-17 19:57:39Z luc $
+ * @author L. Maisonobe
+
+ */
+
+public class ThreeEighthesIntegrator
+  extends RungeKuttaIntegrator {
+
+  private static final String methodName = "3/8";
+
+  private static final double[] c = {
+    1.0 / 3.0, 2.0 / 3.0, 1.0
+  };
+
+  private static final double[][] a = {
+    {  1.0 / 3.0 },
+    { -1.0 / 3.0, 1.0 },
+    {  1.0, -1.0, 1.0 }
+  };
+
+  private static final double[] b = {
+    1.0 / 8.0, 3.0 / 8.0, 3.0 / 8.0, 1.0 / 8.0
+  };
+
+  /** Simple constructor.
+   * Build a 3/8 integrator with the given step.
+   * @param step integration step
+   */
+  public ThreeEighthesIntegrator(double step) {
+    super(false, c, a, b, new ThreeEighthesStepInterpolator(), step);
+  }
+
+  /** Get the name of the method.
+   * @return name of the method
+   */
+  public String getName() {
+    return methodName;
+  }
+
+}

Propchange: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/ThreeEighthesIntegrator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/ThreeEighthesStepInterpolator.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/ThreeEighthesStepInterpolator.java?view=auto&rev=512066
==============================================================================
--- jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/ThreeEighthesStepInterpolator.java (added)
+++ jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/ThreeEighthesStepInterpolator.java Mon Feb 26 15:12:40 2007
@@ -0,0 +1,113 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF 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.apache.commons.math.ode;
+
+/**
+ * This class implements a step interpolator for the 3/8 fourth
+ * order Runge-Kutta integrator.
+
+ * <p>This interpolator allows to compute dense output inside the last
+ * step computed. The interpolation equation is consistent with the
+ * integration scheme :
+
+ * <pre>
+ *   y(t_n + theta h) = y (t_n + h)
+ *                    - (1 - theta) (h/8) [ (1 - 7 theta + 8 theta^2) y'_1
+ *                                      + 3 (1 +   theta - 4 theta^2) y'_2
+ *                                      + 3 (1 +   theta)             y'_3
+ *                                      +   (1 +   theta + 4 theta^2) y'_4
+ *                                        ]
+ * </pre>
+
+ * where theta belongs to [0 ; 1] and where y'_1 to y'_4 are the four
+ * evaluations of the derivatives already computed during the
+ * step.</p>
+
+ * @see ThreeEighthesIntegrator
+
+ * @version $Id: ThreeEighthesStepInterpolator.java 1705 2006-09-17 19:57:39Z luc $
+ * @author L. Maisonobe
+
+ */
+
+class ThreeEighthesStepInterpolator
+  extends RungeKuttaStepInterpolator {
+    
+  /** Simple constructor.
+   * This constructor builds an instance that is not usable yet, the
+   * {@link AbstractStepInterpolator#reinitialize} method should be called
+   * before using the instance in order to initialize the internal arrays. This
+   * constructor is used only in order to delay the initialization in
+   * some cases. The {@link RungeKuttaIntegrator} class uses the
+   * prototyping design pattern to create the step interpolators by
+   * cloning an uninitialized model and latter initializing the copy.
+   */
+  public ThreeEighthesStepInterpolator() {
+  }
+
+  /** Copy constructor.
+   * @param interpolator interpolator to copy from. The copy is a deep
+   * copy: its arrays are separated from the original arrays of the
+   * instance
+   */
+  public ThreeEighthesStepInterpolator(ThreeEighthesStepInterpolator interpolator) {
+    super(interpolator);
+  }
+
+  /**
+   * Clone the instance.
+   * the copy is a deep copy: its arrays are separated from the
+   * original arrays of the instance
+   * @return a copy of the instance
+   */
+  public Object clone() {
+    return new ThreeEighthesStepInterpolator(this);
+  }
+
+  /** Compute the state at the interpolated time.
+   * This is the main processing method that should be implemented by
+   * the derived classes to perform the interpolation.
+   * @param theta normalized interpolation abscissa within the step
+   * (theta is zero at the previous time step and one at the current time step)
+   * @param oneMinusThetaH time gap between the interpolated time and
+   * the current time
+   * @throws DerivativeException this exception is propagated to the caller if the
+   * underlying user function triggers one
+   */
+  protected void computeInterpolatedState(double theta,
+                                          double oneMinusThetaH)
+    throws DerivativeException {
+
+    double fourTheta2 = 4 * theta * theta;
+    double s          = oneMinusThetaH / 8.0;
+    double coeff1     = s * (1 - 7 * theta + 2 * fourTheta2);
+    double coeff2     = 3 * s * (1 + theta - fourTheta2);
+    double coeff3     = 3 * s * (1 + theta);
+    double coeff4     = s * (1 + theta + fourTheta2);
+
+    for (int i = 0; i < interpolatedState.length; ++i) {
+      interpolatedState[i] = currentState[i]
+                            - coeff1 * yDotK[0][i] - coeff2 * yDotK[1][i]
+                            - coeff3 * yDotK[2][i] - coeff4 * yDotK[3][i];
+     }
+
+  }
+
+  private static final long serialVersionUID = -3345024435978721931L;
+
+}

Propchange: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/ThreeEighthesStepInterpolator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/package.html
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/package.html?view=auto&rev=512066
==============================================================================
--- jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/package.html (added)
+++ jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/package.html Mon Feb 26 15:12:40 2007
@@ -0,0 +1,169 @@
+<html>
+<body>
+This package provides classes to solve Ordinary Differential Equations problems.
+
+<p>
+This package solves Initial Value Problems of the form
+<code>y'=f(t,y)</code> with <code>t0</code> and <code>y(t0)=y0</code>
+known. The provided integrators compute an estimate of
+<code>y(t)</code> from <code>t=t0</code> to <code>t=t1</code>.
+</p>
+
+<p>
+All integrators provide dense output. This means that besides
+computing the state vector at discrete times, they also provide a
+cheap mean to get the state between the time steps. They do so through
+classes extending the {@link
+org.spaceroots.mantissa.ode.StepInterpolator StepInterpolator}
+abstract class, which are made available to the user at the end of
+each step.
+</p>
+
+<p>
+All integrators handle multiple switching functions. This means that
+the integrator can be driven by discrete events (occurring when the
+signs of user-supplied {@link
+org.spaceroots.mantissa.ode.SwitchingFunction switching functions}
+change). The steps are shortened as needed to ensure the events occur
+at step boundaries (even if the integrator is a fixed-step
+integrator). When the events are triggered, integration can be stopped
+(this is called a G-stop facility), the state vector can be changed,
+or integration can simply go on. The latter case is useful to handle
+discontinuities in the differential equations gracefully and get
+accurate dense output even close to the discontinuity. The events are
+detected when the functions signs are different at the beginning and
+end of the current step, or at several equidistant points inside the
+step if its length becomes larger than the maximal checking interval
+specified for the given switching function. This time interval should
+be set appropriately to avoid missing some switching function sign
+changes (it is possible to set it to
+<code>Double.POSITIVE_INFINITY</code> if the sign changes cannot be
+missed).
+</p>
+
+<p>
+The user should describe his problem in his own classes
+(<code>UserProblem</code> in the diagram below) which should implement
+the {@link org.spaceroots.mantissa.ode.FirstOrderDifferentialEquations
+FirstOrderDifferentialEquations} interface. Then he should pass it to
+the integrator he prefers among all the classes that implement the
+{@link org.spaceroots.mantissa.ode.FirstOrderIntegrator
+FirstOrderIntegrator} interface. In order to simplify the mapping
+between domain objects and the flat arrays needed in order to
+implement the {@link
+org.spaceroots.mantissa.ode.FirstOrderDifferentialEquations
+FirstOrderDifferentialEquations} interface, the {@link
+org.spaceroots.mantissa.utilities.ArraySliceMappable
+ArraySliceMappable} interface and {@link
+org.spaceroots.mantissa.utilities.ArrayMapper ArrayMapper} class
+provided by the utilities package can be used.
+</p>
+
+<p>
+The solution of the integration problem is provided by two means. The
+first one is aimed towards simple use: the state vector at the end of
+the integration process is copied in the <code>y</code> array of the
+{@link org.spaceroots.mantissa.ode.FirstOrderIntegrator#integrate
+FirstOrderIntegrator.integrate} method. The second one should be used
+when more in-depth information is needed throughout the integration
+process. The user can register an object implementing the {@link
+org.spaceroots.mantissa.ode.StepHandler StepHandler} interface or a
+{@link org.spaceroots.mantissa.ode.StepNormalizer StepNormalizer}
+object wrapping a user-specified object implementing the {@link
+org.spaceroots.mantissa.ode.FixedStepHandler FixedStepHandler}
+interface into the integrator before calling the {@link
+org.spaceroots.mantissa.ode.FirstOrderIntegrator#integrate
+FirstOrderIntegrator.integrate} method. The user object will be called
+appropriately during the integration process, allowing the user to
+process intermediate results. The default step handler does nothing.
+</p>
+
+<p>
+{@link org.spaceroots.mantissa.ode.ContinuousOutputModel
+ContinuousOutputModel} is a special-purpose step handler that is able
+to store all steps and to provide transparent access to any
+intermediate result once the integration is over. An important feature
+of this class is that it implements the <code>Serializable</code>
+interface. This means that a complete continuous model of the
+integrated function througout the integration range can be serialized
+and reused later (if stored into a persistent medium like a filesystem
+or a database) or elsewhere (if sent to another application). Only the
+result of the integration is stored, there is no reference to the
+integrated problem by itself.
+</p>
+
+<p>
+Other default implementations of the {@link
+org.spaceroots.mantissa.ode.StepHandler StepHandler} interface are
+available for general needs ({@link
+org.spaceroots.mantissa.ode.DummyStepHandler DummyStepHandler}, {@link
+org.spaceroots.mantissa.ode.StepNormalizer StepNormalizer}) and custom
+implementations can be developped for specific needs. As an example,
+if an application is to be completely driven by the integration
+process, then most of the application code will be run inside a step
+handler specific to this application.
+</p>
+
+<p>
+Some integrators (the simple ones) use fixed steps that are set at
+creation time. The more efficient integrators use variable steps that
+are handled internally in order to control the integration error with
+respect to a specified accuracy (these integrators extend the {@link
+org.spaceroots.mantissa.ode.AdaptiveStepsizeIntegrator
+AdaptiveStepsizeIntegrator} abstract class). In this case, the step
+handler which is called after each successful step shows up the
+variable stepsize. The {@link
+org.spaceroots.mantissa.ode.StepNormalizer StepNormalizer} class can
+be used to convert the variable stepsize into a fixed stepsize that
+can be handled by classes implementing the {@link
+org.spaceroots.mantissa.ode.FixedStepHandler FixedStepHandler}
+interface. Adaptive stepsize integrators can automatically compute the
+initial stepsize by themselves, however the user can specify it if he
+prefers to retain full control over the integration or if the
+automatic guess is wrong.
+</p>
+
+<p>
+<table border="1" align="center">
+<tr BGCOLOR="#CCCCFF"><td colspan=2><font size="+2">Fixed Step Integrators</font></td></tr>
+<tr BGCOLOR="#EEEEFF"><font size="+1"><td>Name</td><td>Order</td></font></tr>
+<tr><td>{@link org.spaceroots.mantissa.ode.EulerIntegrator Euler}</td><td>1</td></tr>
+<tr><td>{@link org.spaceroots.mantissa.ode.MidpointIntegrator Midpoint}</td><td>2</td></tr>
+<tr><td>{@link org.spaceroots.mantissa.ode.ClassicalRungeKuttaIntegrator Classical Runge-Kutta}</td><td>4</td></tr>
+<tr><td>{@link org.spaceroots.mantissa.ode.GillIntegrator Gill}</td><td>4</td></tr>
+<tr><td>{@link org.spaceroots.mantissa.ode.ThreeEighthesIntegrator 3/8}</td><td>4</td></tr>
+</table>
+</p>
+
+<table border="1" align="center">
+<tr BGCOLOR="#CCCCFF"><td colspan=3><font size="+2">Adaptive Stepsize Integrators</font></td></tr>
+<tr BGCOLOR="#EEEEFF"><font size="+1"><td>Name</td><td>Integration Order</td><td>Error Estimation Order</td></font></tr>
+<tr><td>{@link org.spaceroots.mantissa.ode.HighamHall54Integrator Higham and Hall}</td><td>5</td><td>4</td></tr>
+<tr><td>{@link org.spaceroots.mantissa.ode.DormandPrince54Integrator Dormand-Prince 5(4)}</td><td>5</td><td>4</td></tr>
+<tr><td>{@link org.spaceroots.mantissa.ode.DormandPrince853Integrator Dormand-Prince 8(5,3)}</td><td>8</td><td>5 and 3</td></tr>
+<tr><td>{@link org.spaceroots.mantissa.ode.GraggBulirschStoerIntegrator Gragg-Bulirsch-Stoer}</td><td>variable (up to 18 by default)</td><td>variable</td></tr>
+</table>
+</p>
+
+<p>
+The class diagram below shows a typical example use of this
+package. The orange boxes are the classes the user should develop, the
+white boxes are the interfaces and classes already provided by the
+library. The main application build an ODE problem that involve
+several domain objects (for example the orbit of a spacecraft and its
+attitude) which are mapped into one flat array representing the state
+vector using an ArrayMapper object. The UserProblem object is provided
+by the main application to an integrator (in this exemple the
+Gragg-Bulirsch-Stoer integrator has been chosen) together with a step
+handler (in this exemple the already existing ContinuousOutputModel
+class has been chosen). In this case, the user waits until the end of
+integration before continuing his own processing, and uses the
+ContinuousOutputModel object to navigate throughout the integration
+interval once it has been filled up by the integrator.
+</p>
+
+<img src="doc-files/org_spaceroots_mantissa_ode_classes.png" />
+
+@author L. Maisonobe
+</body>
+</html>

Propchange: jakarta/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/package.html
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: jakarta/commons/proper/math/trunk/src/test/org/apache/commons/math/ode/ClassicalRungeKuttaIntegratorTest.java (from r512064, jakarta/commons/proper/math/trunk/src/mantissa/tests-src/org/spaceroots/mantissa/ode/ClassicalRungeKuttaIntegratorTest.java)
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/math/trunk/src/test/org/apache/commons/math/ode/ClassicalRungeKuttaIntegratorTest.java?view=diff&rev=512066&p1=jakarta/commons/proper/math/trunk/src/mantissa/tests-src/org/spaceroots/mantissa/ode/ClassicalRungeKuttaIntegratorTest.java&r1=512064&p2=jakarta/commons/proper/math/trunk/src/test/org/apache/commons/math/ode/ClassicalRungeKuttaIntegratorTest.java&r2=512066
==============================================================================
--- jakarta/commons/proper/math/trunk/src/mantissa/tests-src/org/spaceroots/mantissa/ode/ClassicalRungeKuttaIntegratorTest.java (original)
+++ jakarta/commons/proper/math/trunk/src/test/org/apache/commons/math/ode/ClassicalRungeKuttaIntegratorTest.java Mon Feb 26 15:12:40 2007
@@ -15,13 +15,17 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.spaceroots.mantissa.ode;
+package org.apache.commons.math.ode;
 
 import junit.framework.*;
 
-import org.spaceroots.mantissa.estimation.EstimationException;
-import org.spaceroots.mantissa.estimation.LevenbergMarquardtEstimator;
-import org.spaceroots.mantissa.fitting.PolynomialFitter;
+import org.apache.commons.math.ode.ClassicalRungeKuttaIntegrator;
+import org.apache.commons.math.ode.DerivativeException;
+import org.apache.commons.math.ode.FirstOrderIntegrator;
+import org.apache.commons.math.ode.IntegratorException;
+import org.apache.commons.math.ode.StepHandler;
+import org.apache.commons.math.ode.StepInterpolator;
+import org.apache.commons.math.ode.SwitchingFunction;
 
 public class ClassicalRungeKuttaIntegratorTest
   extends TestCase {
@@ -86,47 +90,6 @@
         }
         previousError = error;
       }
-
-    }
-
-  }
-
-  public void testOrder()
-  throws EstimationException, DerivativeException,
-         IntegratorException {
-    PolynomialFitter fitter =
-      new PolynomialFitter(1, new LevenbergMarquardtEstimator());
-
-    TestProblemAbstract[] problems = TestProblemFactory.getProblems();
-    for (int k = 0; k < problems.length; ++k) {
-
-      for (int i = 0; i < 10; ++i) {
-
-        TestProblemAbstract pb = (TestProblemAbstract) problems[k].clone();
-        double step = (pb.getFinalTime() - pb.getInitialTime())
-          * Math.pow(2.0, -(i + 1));
-
-        FirstOrderIntegrator integ = new ClassicalRungeKuttaIntegrator(step);
-        TestProblemHandler handler = new TestProblemHandler(pb);
-        integ.setStepHandler(handler);
-        SwitchingFunction[] functions = pb.getSwitchingFunctions();
-        for (int l = 0; l < functions.length; ++l) {
-          integ.addSwitchingFunction(functions[l],
-                                     Double.POSITIVE_INFINITY, 1.0e-6 * step);
-        }
-        integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(),
-                        pb.getFinalTime(), new double[pb.getDimension()]);
-
-        fitter.addWeightedPair(1.0,
-                               Math.log(Math.abs(step)),
-                               Math.log(handler.getLastError()));
-
-      }
-
-      // this is an order 4 method
-      double[] coeffs = fitter.fit();
-      assertTrue(coeffs[1] > 3.2);
-      assertTrue(coeffs[1] < 4.8);
 
     }
 

Copied: jakarta/commons/proper/math/trunk/src/test/org/apache/commons/math/ode/ClassicalRungeKuttaStepInterpolatorTest.java (from r512064, jakarta/commons/proper/math/trunk/src/mantissa/tests-src/org/spaceroots/mantissa/ode/ClassicalRungeKuttaStepInterpolatorTest.java)
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/math/trunk/src/test/org/apache/commons/math/ode/ClassicalRungeKuttaStepInterpolatorTest.java?view=diff&rev=512066&p1=jakarta/commons/proper/math/trunk/src/mantissa/tests-src/org/spaceroots/mantissa/ode/ClassicalRungeKuttaStepInterpolatorTest.java&r1=512064&p2=jakarta/commons/proper/math/trunk/src/test/org/apache/commons/math/ode/ClassicalRungeKuttaStepInterpolatorTest.java&r2=512066
==============================================================================
--- jakarta/commons/proper/math/trunk/src/mantissa/tests-src/org/spaceroots/mantissa/ode/ClassicalRungeKuttaStepInterpolatorTest.java (original)
+++ jakarta/commons/proper/math/trunk/src/test/org/apache/commons/math/ode/ClassicalRungeKuttaStepInterpolatorTest.java Mon Feb 26 15:12:40 2007
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.spaceroots.mantissa.ode;
+package org.apache.commons.math.ode;
 
 import junit.framework.*;
 import java.util.Random;
@@ -24,6 +24,11 @@
 import java.io.ObjectOutputStream;
 import java.io.ObjectInputStream;
 import java.io.IOException;
+
+import org.apache.commons.math.ode.ClassicalRungeKuttaIntegrator;
+import org.apache.commons.math.ode.ContinuousOutputModel;
+import org.apache.commons.math.ode.DerivativeException;
+import org.apache.commons.math.ode.IntegratorException;
 
 public class ClassicalRungeKuttaStepInterpolatorTest
   extends TestCase {



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org