package jmathlib.toolbox.funfun;
/* This file is part or JMATHLIB
* author: Stefan Mueller 03/27/2005 initial version
* */
import jmathlib.core.tokens.*;
import jmathlib.core.tokens.numbertokens.DoubleNumberToken;
import jmathlib.core.functions.ExternalFunction;
import jmathlib.core.interpreter.GlobalValues;
/**An external function for computing a mesh of a matrix */
public class euler extends ExternalFunction
{
/**integrates a "function" using the euler forward integration method
* [t,y] = euler (function, [t0 tf], y0, dt)
*/
public OperandToken evaluate(Token[] operands, GlobalValues globals)
{
// [t,y] = euler (function, [t0 tf], y0, dt)
if (getNArgIn(operands)!=4)
throwMathLibException("euler: number of input arguments != 4");
// Check number of return arguments
if (getNoOfLeftHandArguments()!=2)
throwMathLibException("euler: number of output arguments != 2");
if ( !(operands[0] instanceof CharToken) ||
!(operands[1] instanceof DoubleNumberToken) ||
!(operands[2] instanceof DoubleNumberToken) ||
!(operands[3] instanceof DoubleNumberToken) )
throwMathLibException("euler: wrong typ or types of parameters");
// get name of function to integrate
String funcName = ((CharToken)operands[0]).toString();
// get time span: initial time (t0) and final time (tf)
double[][] t_span = ((DoubleNumberToken)operands[1]).getReValues();
if ((t_span.length != 1) || (t_span[0].length != 2))
throwMathLibException("euler: need [t0 tf]");
double t0= t_span[0][0];
double tf= t_span[0][1];
// check if t0 < tf
if (t0>=tf)
throwMathLibException("euler: start time must be smaller than end time");
// get initial state
double[][] y0 = ((DoubleNumberToken)operands[2]).getReValues();
if (y0.length != 1)
throwMathLibException("euler: initial conditions work only row vectors");
// length of state vector (always use row vector)
int m = y0[0].length;
// get step size
double dt = ((DoubleNumberToken)operands[3]).getValueRe();
// calculate number of integration steps
int n = new Double(Math.round((tf-t0)/dt)).intValue();
// initialize time and output arrays [n rows, initial conditions size rows]
double[][] t = new double[n][1];
double[][] y_out = new double[n][m];
System.out.println("t0 = "+t0);
System.out.println("tf = "+tf);
// create function which will be used for integration
//FunctionToken function = new FunctionToken(funcName);
// preparation of initial conditions
int k=1;
double[][] y = new double[m][1]; // state is a column vector
for (int i=0; i< m; i++)
{
//System.out.println("y("+i+")= "+y0[i][0]);
y[i][0] = y0[0][i]; // row vector -> column vector
y_out[0][i] = y0[0][i]; // y(t=t0)
}
// loop to integrate function
while(k<n)
{
//System.out.println("k = "+k);
FunctionToken function = new FunctionToken(funcName);
// set up operands for integrated function
OperandToken[] op = new OperandToken[2];
op[0]=new DoubleNumberToken(t0 + k * dt);
op[1]=new DoubleNumberToken(y);
function.setOperands(op);
//evaluate function
OperandToken result = function.evaluate(null, globals);
// retrieve output vector of integration
if ( !(result instanceof DoubleNumberToken) )
throwMathLibException("euler: wrong return type of function");
// build output
double[][] y_ret = ((DoubleNumberToken)result).getReValues();
for (int i=0; i< m; i++)
{
//System.out.println("dy("+k+" "+i+")= "+y_ret[i][0]);
y_out[k][i] = y_out[k-1][i] + y_ret[i][0] * dt;
//System.out.println("y("+k+" "+i+")= "+y_out[k][i]);
y[i][0] = y_out[k][i];
}
t[k][0] = t0 + k * dt;
k++;
} // end integration loop
OperandToken values[][] = new OperandToken[1][2];
values[0][0] = new DoubleNumberToken(t);
values[0][1] = new DoubleNumberToken(y_out);
return new MatrixToken( values );
} // end eval
}
/*
@GROUP
FunFun
@SYNTAX
[t,y] = euler (function, [t0 tf], y0, dt)
@DOC
Integration of a given function using Euler's method.
@EXAMPLES
[t,y]=euler('vdp1',[0,10],[2,0],0.1)
@NOTES
@SEE
*/