--- 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))))))


Reply via email to