⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 embeddedrungekuttaintegrator.java

📁 Apache的common math数学软件包
💻 JAVA
字号:
/* * 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 embedded Runge-Kutta * integrators for Ordinary Differential Equations. * * <p>These methods are embedded explicit Runge-Kutta methods with two * sets of coefficients allowing to estimate the error, their Butcher * arrays are as follows : * <pre> *    0  | *   c2  | a21 *   c3  | a31  a32 *   ... |        ... *   cs  | as1  as2  ...  ass-1 *       |-------------------------- *       |  b1   b2  ...   bs-1  bs *       |  b'1  b'2 ...   b's-1 b's * </pre> * </p> * * <p>In fact, we rather use the array defined by ej = bj - b'j to * compute directly the error rather than computing two estimates and * then comparing them.</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> * * @version $Revision: 620312 $ $Date: 2008-02-10 12:28:59 -0700 (Sun, 10 Feb 2008) $ * @since 1.2 */public abstract class EmbeddedRungeKuttaIntegrator  extends AdaptiveStepsizeIntegrator {  /** Build a Runge-Kutta integrator with the given Butcher array.   * @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 propagation weights for the high order method from Butcher array   * @param prototype prototype of the step interpolator to use   * @param minStep minimal step (must be positive even for backward   * integration), the last step can be smaller than this   * @param maxStep maximal step (must be positive even for backward   * integration)   * @param scalAbsoluteTolerance allowed absolute error   * @param scalRelativeTolerance allowed relative error   */  protected EmbeddedRungeKuttaIntegrator(boolean fsal,                                         double[] c, double[][] a, double[] b,                                         RungeKuttaStepInterpolator prototype,                                         double minStep, double maxStep,                                         double scalAbsoluteTolerance,                                         double scalRelativeTolerance) {    super(minStep, maxStep, scalAbsoluteTolerance, scalRelativeTolerance);    this.fsal      = fsal;    this.c         = c;    this.a         = a;    this.b         = b;    this.prototype = prototype;    exp = -1.0 / getOrder();    // set the default values of the algorithm control parameters    setSafety(0.9);    setMinReduction(0.2);    setMaxGrowth(10.0);  }  /** Build a Runge-Kutta integrator with the given Butcher array.   * @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 propagation weights for the high order method from Butcher array   * @param prototype prototype of the step interpolator to use   * @param minStep minimal step (must be positive even for backward   * integration), the last step can be smaller than this   * @param maxStep maximal step (must be positive even for backward   * integration)   * @param vecAbsoluteTolerance allowed absolute error   * @param vecRelativeTolerance allowed relative error   */  protected EmbeddedRungeKuttaIntegrator(boolean fsal,                                         double[] c, double[][] a, double[] b,                                         RungeKuttaStepInterpolator prototype,                                         double   minStep, double maxStep,                                         double[] vecAbsoluteTolerance,                                         double[] vecRelativeTolerance) {    super(minStep, maxStep, vecAbsoluteTolerance, vecRelativeTolerance);    this.fsal      = fsal;    this.c         = c;    this.a         = a;    this.b         = b;    this.prototype = prototype;    exp = -1.0 / getOrder();    // set the default values of the algorithm control parameters    setSafety(0.9);    setMinReduction(0.2);    setMaxGrowth(10.0);  }  /** Get the name of the method.   * @return name of the method   */  public abstract String getName();  /** Get the order of the method.   * @return order of the method   */  public abstract int getOrder();  /** Get the safety factor for stepsize control.   * @return safety factor   */  public double getSafety() {    return safety;  }  /** Set the safety factor for stepsize control.   * @param safety safety factor   */  public void setSafety(double safety) {    this.safety = safety;  }  /** Integrate the differential equations up to the given time.   * <p>This method solves an Initial Value Problem (IVP).</p>   * <p>Since this method stores some internal state variables made   * available in its public interface during integration ({@link   * #getCurrentSignedStepsize()}), it is <em>not</em> 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</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   * @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(FirstOrderDifferentialEquations equations,                        double t0, double[] y0,                        double t, double[] y)  throws DerivativeException, IntegratorException {    sanityChecks(equations, t0, y0, t, y);    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.copy();      rki.reinitialize(equations, yTmp, yDotK, forward);      interpolator = rki;    } else {      interpolator = new DummyStepInterpolator(yTmp, forward);    }    interpolator.storeTime(t0);    stepStart  = t0;    double  hNew      = 0;    boolean firstTime = true;    boolean lastStep;    handler.reset();    do {      interpolator.shift();      double error = 0;      for (boolean loop = true; loop;) {        if (firstTime || !fsal) {          // first stage          equations.computeDerivatives(stepStart, y, yDotK[0]);        }        if (firstTime) {          double[] scale;          if (vecAbsoluteTolerance != null) {            scale = vecAbsoluteTolerance;          } else {            scale = new double[y0.length];            for (int i = 0; i < scale.length; ++i) {              scale[i] = scalAbsoluteTolerance;            }          }          hNew = initializeStep(equations, forward, getOrder(), scale,                                stepStart, y, yDotK[0], yTmp, yDotK[1]);          firstTime = false;        }        stepSize = hNew;        // step adjustment near bounds        if ((forward && (stepStart + stepSize > t)) ||            ((! forward) && (stepStart + stepSize < t))) {          stepSize = t - stepStart;        }        // 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] + stepSize * sum;          }          equations.computeDerivatives(stepStart + c[k-1] * stepSize, 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] + stepSize * sum;        }        // estimate the error at the end of the step        error = estimateError(yDotK, y, yTmp, stepSize);        if (error <= 1.0) {          // Switching functions handling          interpolator.storeTime(stepStart + stepSize);          if (switchesHandler.evaluateStep(interpolator)) {            // reject the step to match exactly the next switch time            hNew = switchesHandler.getEventTime() - stepStart;          } else {            // accept the step            loop = false;          }        } else {          // reject the step and attempt to reduce error by stepsize control          double factor = Math.min(maxGrowth,                                   Math.max(minReduction,                                            safety * Math.pow(error, exp)));          hNew = filterStep(stepSize * factor, false);        }      }      // the step has been accepted      double nextStep = stepStart + stepSize;      System.arraycopy(yTmp, 0, y, 0, y0.length);      switchesHandler.stepAccepted(nextStep, y);      if (switchesHandler.stop()) {        lastStep = true;      } else {        lastStep = forward ? (nextStep >= t) : (nextStep <= t);      }      // provide the step data to the step handler      interpolator.storeTime(nextStep);      handler.handleStep(interpolator, lastStep);      stepStart = nextStep;      if (fsal) {        // save the last evaluation for the next step        System.arraycopy(yDotK[stages - 1], 0, yDotK[0], 0, y0.length);      }      if (switchesHandler.reset(stepStart, y) && ! lastStep) {        // some switching function has triggered changes that        // invalidate the derivatives, we need to recompute them        equations.computeDerivatives(stepStart, y, yDotK[0]);      }      if (! lastStep) {        // stepsize control for next step        double  factor     = Math.min(maxGrowth,                                      Math.max(minReduction,                                               safety * Math.pow(error, exp)));        double  scaledH    = stepSize * factor;        double  nextT      = stepStart + scaledH;        boolean nextIsLast = forward ? (nextT >= t) : (nextT <= t);        hNew = filterStep(scaledH, nextIsLast);      }    } while (! lastStep);    resetInternalState();  }  /** Get the minimal reduction factor for stepsize control.   * @return minimal reduction factor   */  public double getMinReduction() {    return minReduction;  }  /** Set the minimal reduction factor for stepsize control.   * @param minReduction minimal reduction factor   */  public void setMinReduction(double minReduction) {    this.minReduction = minReduction;  }  /** Get the maximal growth factor for stepsize control.   * @return maximal growth factor   */  public double getMaxGrowth() {    return maxGrowth;  }  /** Set the maximal growth factor for stepsize control.   * @param maxGrowth maximal growth factor   */  public void setMaxGrowth(double maxGrowth) {    this.maxGrowth = maxGrowth;  }  /** Compute the error ratio.   * @param yDotK derivatives computed during the first stages   * @param y0 estimate of the step at the start of the step   * @param y1 estimate of the step at the end of the step   * @param h  current step   * @return error ratio, greater than 1 if step should be rejected   */  protected abstract double estimateError(double[][] yDotK,                                          double[] y0, double[] y1,                                          double h);  /** 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;                                           /** Stepsize control exponent. */  private double exp;  /** Safety factor for stepsize control. */  private double safety;  /** Minimal reduction factor for stepsize control. */  private double minReduction;  /** Maximal growth factor for stepsize control. */  private double maxGrowth;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -