001    import org.apache.commons.math3.ode.*;
002    
003    /** Wrapper used to pass a <i>system of first order 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 as {@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      */
009    public 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    }