001import org.apache.commons.math3.ode.*;
002
003/** Wrapper used to pass a <i>system of first order ordinary differential equations</i> (odes) to <a target="_blank" href="http://commons.apache.org/math">Commons Math</a> algorithms.
004  * Computes the derivatives {@code dy}<sub>i</sub>{@code /dt} defined in the &nbsp;{@code String[] odes}.<br/>
005  * <br/>
006  * See <a target="_top" href="../0_CommonsMath_README.html#examples">CommonsMath_ODE_Lotka_Volterra~Test.jxn</a>
007  * for an example.  
008  */
009public class JxnODE implements FirstOrderDifferentialEquations
010{
011   KmgFormelInterpreter fi;
012   static final boolean skipInputLogEnabled = true;
013   
014   String itsInit = "";
015   String [] itsOdes;
016
017   /** Constructs a {@link org.apache.commons.math3.ode.FirstOrderDifferentialEquations}
018     * instance to be used by <a target="_blank" href="http://commons.apache.org/math">Commons Math</a> algorithms. <br/>
019     * Example:
020     * <pre>
021     *    ode = @JxODE( $this, { "$y[0]*( a - b $y[1] );", "$y[1]*( d $y[0] - c );" } )
022     * </pre>
023     * @param fi instance of {@code KmgFormelInterpreter} on which the definitions in {@code odes[...]} are executed
024     * @param odes array of <i>statement_sequence</i>s (one or more statements separated by '{@code ;}').
025     * The definitions in {@code odes[...]} must use {@code double[] $y} and {@code $t} to calculate the derivatives {@code dy/dt}. 
026     * If the definition in {@code odes[i]} ends with '{@code ;}', log output of intermediate steps is suppressed for the definition.
027     */
028   public JxnODE( KmgFormelInterpreter fi, String [] odes )
029   {
030      this.fi = fi;
031      itsOdes = odes;
032   }
033   
034   /** See {@link #JxnODE}.
035     * @param init <i>statement_sequence</i> (one or more statements separated by '{@code ;}'). {@code init} is evaluated before evaluating {@code odes} and
036     * can use {@code double[] $y} and {@code $t}. If {@code init} ends with '{@code ;}', log output is suppressed.
037     * @param parameters the values can be used in the {@code init} and {@code odes} definitions via the array variable {@code $p[...]}
038     */
039   public JxnODE( KmgFormelInterpreter fi, String init, String [] odes, double [] parameters )
040   {
041      this.fi = fi;
042      itsInit = init;
043      itsOdes = odes;
044      
045      fi.put( "$p", parameters );
046   }
047   
048// --- interface FirstOrderDifferentialEquations ---
049
050   /** Returns the number of states. */
051   public int getDimension()
052   {
053      return itsOdes.length;
054   }
055
056   /** Computes derivatives {@code ydot} from {@code y} and {@code t} (internally called by Commons Math algorithms). */
057   public void computeDerivatives( double t, double [] y, double [] ydot )
058   {
059   // store values
060      fi.put( "$t", new JxnPrimitiveWrapper(t) );
061      fi.put( "$y", y );
062      if( itsInit.length() > 0 ) fi.execute( itsInit, skipInputLogEnabled );
063      
064   // calculate derivatives
065      for( int i = 0; i < itsOdes.length; i++ )
066      {
067         ydot[i] = KmgFormelInterpreter.doubleValue( fi.execute( itsOdes[i], skipInputLogEnabled ) );
068      }    
069   }
070   
071   public String toString()
072   {
073      return itsOdes.length + " ODEs";
074   }
075}