--- Raymond Toy <[EMAIL PROTECTED]> wrote:
> If it's not too large, could you just send the Lisp callback
routines?
> That should give some hints on what's happening even if we don't have
> the foreign libraries.
I'll send what's manageable. I forgot one level of callback.
It's actually: Lisp -> C -> Lisp -> C if you can believe it.
Here are the relevant alien definitions.
;; These are C functions called from the Lisp system of equations
function.
(def-alien-routine get_sysvar_n int)
(def-alien-routine get_sysvar_val double (i int))
(def-alien-routine get_sysvar_dotval double (i int))
(def-alien-routine set_sysvar_val void (i int) (x double))
(def-alien-routine set_sysvar_dotval void (i int) (x double))
;; these C functions are called once per complete simulation
(def-alien-routine init_dims void (nsys_var int) (nparam int)
;; this registers the Lisp callback for the system of equations
(model (* (function void (double-float)))))
(def-alien-routine mem_alloc int)
(def-alien-routine mem_free void)
(def-alien-routine fill_in int (start_time double)
(init_vals (* double-float)) (sa int))
(def-alien-routine init_cvode void (init_vals (* double-float))
(start_time double))
(def-alien-routine sim_model_cvode int
(sample_time double))
The system of equations is built dynamically. Slightly edited
code for this is included below and an example function is
given at the end of the email:
(defun cvode-make-MS-model (system sa?)
`(progn
,(append
'(def-callback MS_model (void (time c-call:double))
(declare (optimize (speed 3) (safety 0))))
;; this adds some general Lisp code
(assign-exo-vars (getv-exogenous-variables) 'time)
;; this adds Lisp code that calls C functions (see below)
(cvode-assign-sys-vars)
;; this adds more Lisp code that calls some C functions
(cvode-generate-f-equations system sa? t))))
;; this builds a part of the equations that calls C from
;; Lisp: get_sysvar_val(i), is a simple function that lets
;; Lisp access an array stored in C.
(defun cvode-assign-sys-vars ()
(let ((syslst))
(dotimes (i (length *system-variables*) syslst)
(push `(setf (aref *system-variables* ,i)
(get_sysvar_val ,i))
syslst))))
;; here's the declaration of get_sysvar_val from above
double get_sysvar_val(int i) {return sys_var.vals[i];}
;; i call this function once for each of n variables for each
;; explicit time step passed to the solver. so, for one full
;; simulation, this function could be called hundreds of
;; times.
;; here's a note that I wrote myself regarding Clisp that might
;; be helpful when thinking about CMUCL:
;;; when clisp calls the function get_sysvar_val, it allocates 16
;;; bytes of memory in which it stores the return value. each call to
;;; get_sysvar_val grabs 16 more bytes, which can add up to a
;;; substantial amount of memory (and GC calls) during simulation.
;;; so, we duplicate the values of the system variables locally (i.e.,
in
;;; Lisp) to speed up access time and to avoid unnecessary garbage.
Finally, here is an example system of equations generated during
runtime.
(DEF-CALLBACK MS_MODEL
(VOID
(TIME
DOUBLE))
(DECLARE (OPTIMIZE (SPEED 3) (SAFETY 0)))
(SETF (AREF *SYSTEM-VARIABLES* 1) (GET_SYSVAR_VAL 1))
(SETF (AREF *SYSTEM-VARIABLES* 0) (GET_SYSVAR_VAL 0))
(SET_SYSVAR_DOTVAL 1
(EQUATION-AGGREGATOR
#<Function + {101AEC21}>
(* -1.0d0
(THE DOUBLE-FLOAT
(AREF *MODEL-CONSTANTS*
3))
(THE DOUBLE-FLOAT
(AREF *SYSTEM-VARIABLES*
1))
(THE DOUBLE-FLOAT
(AREF *SYSTEM-VARIABLES*
0)))
(*
(THE DOUBLE-FLOAT
(AREF *MODEL-CONSTANTS* 1))
(THE DOUBLE-FLOAT
(AREF *SYSTEM-VARIABLES*
1))
(- 1
(*
(THE DOUBLE-FLOAT
(AREF *MODEL-CONSTANTS*
0))
(THE DOUBLE-FLOAT
(AREF
*SYSTEM-VARIABLES*
1)))))))
(SET_SYSVAR_DOTVAL 0
(EQUATION-AGGREGATOR
#<Function + {101AEC21}>
(*
(THE DOUBLE-FLOAT
(AREF *MODEL-CONSTANTS* 4))
(THE DOUBLE-FLOAT
(AREF *MODEL-CONSTANTS* 3))
(THE DOUBLE-FLOAT
(AREF *SYSTEM-VARIABLES*
1))
(THE DOUBLE-FLOAT
(AREF *SYSTEM-VARIABLES*
0)))
(* -1.0d0
(THE DOUBLE-FLOAT
(AREF *MODEL-CONSTANTS*
2))
(THE DOUBLE-FLOAT
(AREF *SYSTEM-VARIABLES*
0))))))