\ ------------------------------------------------------------------------------
\                          ** Loading required modules **
\needs callback include callback.fs
\needs gsl include gsl.fs
\needs locals include locals.fs
\needs vectors include vtest.fs

\ also dos
also vectors also gsl also float 

\ ------------------------------------------------------------------------------
/* from GSL reference:
The following program solves the second-order nonlinear Van der Pol oscillator
equation,

x''(t) + μx'(t)(x(t)2 − 1) + x(t) = 0

This can be converted into a first order system suitable for use with the
ODE GSL routines by introducing a separate variable for the velocity, y = x'(t),

x' = y
y' = −x + μy( 1 − 2x )

The program begins by defining functions for these derivatives and their
Jacobian. This example uses fixed interval. */

: _func ( t y[ f[ mu -- r )
    fdrop f@
    2 pvector swap 2 pvector swap
    { y[ f[ |
    y[ 1 ]@ f[ 0 ]!
    y[ 0 ]@ fdup f* !1 f- y[ 1 ]@ f* f* fnegate
    y[ 0 ]@ f- f[ 1 ]!
    ( y[ ]free ) f[ ]free
    GSL_SUCCESS } ;
: _jac ( t y[ dfdy dfdt[ mu -- r )
    fdrop f@
    2 pvector
    swap 2 2 2 pmatrix
    rot 2 pvector
    { dfdt[ m[[ y[ f: mu |
    !0.0 m[[ 0 0 ]]!  !1.0 m[[ 0 1 ]]!
    y[ 0 ]@ y[ 1 ]@ f* mu f* !-2.0 f* !1 f-
    m[[ 1 0 ]]!
    y[ 0 ]@ fdup f* !1 f- mu f* fnegate
    m[[ 1 1 ]]!    
    !0 dfdt[ 0 ]! !0 dfdt[ 1 ]!    
    m[[ ]]free dfdt[ ]free y[ ]free
    GSL_SUCCESS } ;

' _func gsl_odeiv_func4:1 func
' _jac  gsl_odeiv_jac5:1 jac

func' gsl_odeiv_step_rk4 @ 2 gsl_odeiv_step_alloc constant s

fvariable mu !10 mu f!

sizeof gsl_odeiv_system allocate throw constant sys
func sys gsl_odeiv_system func !
jac sys gsl_odeiv_system jac !
2 sys gsl_odeiv_system dim !
mu sys gsl_odeiv_system params !

fvariable t !0 t df!
!100 fconstant t1
fvariable h 1e-2 h df!
2 fvector y[ !1 y[ 0 ]! !0 y[ 1 ]!
2 fvector y_err[
2 fvector dydt_in[
2 fvector dydt_out[

\ * initialise dydt_in from system parameters * /
t df@ y[ ]data dydt_in[ ]data mu _func drop

: iterate ( -- )
    begin t df@ t1 f< while
	    s t df@ h df@ y[ ]data y_err[ ]data dydt_in[ ]data
	    dydt_out[ ]data sys gsl_odeiv_step_apply
	    IF LEAVE THEN
	    dydt_in[ dydt_out[ ]copy] h df@ t df@ f+ t df!
	    t df@ f. y[ ]print cr
    repeat ;

100 vector* dup 1 swap 0 )! )free

iterate

s gsl_odeiv_step_free
bye