/* ex5.c
 * Example of use of MATLAB Math Library directly from C.
 * This main program uses the ordinary differential equation solver
 * "ode23" to compute a trajectory of the Lorenz equations. */

#include <stdio.h>
#include <string.h>
#include <math.h>
#include "matrix.h"
#include "matlab.h"

/*
 * This function defines the Lorenz equations.  It is called by the
 * differential equation solver, mlfOde23, which is called by the
 * main program.
 */

double SIGMA, RHO, BETA;

Matrix *lorenz( Matrix *tm, Matrix *ym)
{
    /* The input is a 1-by-1 matrix containing the value of t,
     * and a 3-by-1 matrix containing the values of y.
     * The result should be a new 3-by-1 matrix containing the
     * values of the three derivatives. */

    Matrix *ypm;
    Real *y, *yp;

    ypm = mxCreateFull(3,1,0);
    y = mxGetPr(ym);
    yp = mxGetPr(ypm);
    
    yp[0] = -BETA*y[0] + y[1]*y[2];
    yp[1] = -SIGMA*y[1] + SIGMA*y[2];
    yp[2] = -y[0]*y[1] + RHO*y[1] - y[2];
    
    return(ypm);
}

int main( )
{
    /* Initial value of y, a vector with three components.  */

    Real ys[] = {10., 10., 10.};

    Real *t, *y1, *y2, *y3;
    int k, n;
    Matrix *ysm, *tm, *ym, *tsm, *tfm;
    
    /* Assign values to the equation parameters.  */

    SIGMA = 10.;
    RHO = 28.;
    BETA = 8./3.;

    /* Create matrices containing the initial and final values of t.  */

    tsm = mlfScalar(0);
    tfm = mlfScalar(50);
    ysm = mxCreateFull(1,3,0);  memcpy(mxGetPr(ysm), ys, sizeof(ys));
    
    /* Call the library routine.
     * The return value and the first argument are the two output matrices. 
     * The second argument points to the function defining the equations.
     * The next three arguments are required input parameters.
     * The last argument is an optional input parameter, unused here.  */

    tm = mlfOde23( &ym, (void *)lorenz, tsm, tfm, ysm, 0 );

    /* The results are a vector t, and a matrix y with three columns.
     * The number of elments in t is the number of steps taken.
     * Each of the columns in y has the same number of elements.  */

    n = mxGetM(tm);
    t = mxGetPr(tm);
    y1 = mxGetPr(ym);
    y2 = y1 + n;
    y3 = y2 + n;

    /* Print one line for each time step.  */

    mlfPrintf("      t         y1        y2        y3\n");
    for (k = 0; k < n; k++) {
       mlfPrintf("%9.3f %9.3f %9.3f %9.3f\n",t[k],y1[k],y2[k],y3[k]);
    }

    mxFreeMatrix( tsm );
    mxFreeMatrix( tfm );
    mxFreeMatrix( ysm );
    mxFreeMatrix( tm );
    mxFreeMatrix( ym );
    exit(0);
}

