File: utilities.lisp

package info (click to toggle)
cl-geodesics 20010214-9
  • links: PTS, VCS
  • area: contrib
  • in suites: lenny
  • size: 104 kB
  • ctags: 56
  • sloc: lisp: 511; makefile: 44
file content (67 lines) | stat: -rw-r--r-- 2,180 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
;;; to generalize, we need a DEFINE-SYSTEM macro that defines a bunch
;;; of things including
;;;
;;; (a) INTEGRATE-SYSTEM &rest initial-conditions
;;; (b) WITH-STOP-CONDITION
;;; (c) ...
(import '(geodesics:dx/dp
	  geodesics:d2t/dp2
	  geodesics:d2y/dp2))

(defmacro with-stop-condition ((fbody &key maximum-time) &body body)
  (let ((arg (gensym))
	(secs (gensym)))
    (if maximum-time
	`(let (,secs)
	   (let ((*stop-function*
		  (lambda (,arg)
		    (symbol-macrolet ((p (nth 0 ,arg))
				      (tdot (nth 1 ,arg))
				      (time (nth 2 ,arg))
				      (ydot (nth 3 ,arg))
				      (y (nth 4 ,arg))
				      (x (nth 5 ,arg)))
		      (unless ,secs
			(setf ,secs (get-universal-time)))
		      (or (> (get-universal-time) (+ ,secs ,maximum-time))
			  ,fbody)))))
	     ,@body))
      `(let ((*stop-function*
	      (lambda (,arg)
		(symbol-macrolet ((p (nth 0 ,arg))
				  (tdot (nth 1 ,arg))
				  (time (nth 2 ,arg))
				  (ydot (nth 3 ,arg))
				  (y (nth 4 ,arg))
				  (x (nth 5 ,arg)))
		  ,fbody))))
	 ,@body))))

(defmacro with-logging-to-file (f &body body)
  (let ((s (gensym))
	(file (gensym)))
    ;; only evaluate f once, and don't capture variables either.
    `(let ((,file ,f)) 
       (with-open-file (,s ,file :direction :output :if-exists :supersede)
	 (let ((*log* ,s))
	   ,@body)))))

(setf *integrator* (make-adaptive-integrator #'runge-kutta 5))

(defun invert (fn value &key min max)
  ;; uses linear interpolation. With extreme loss of generality:
  (let ((min (or min 0.001d0))
	(max (or max 1000d0)))
    ;; allow the user to fix the assumption.
    (assert (not (= (signum (- (funcall fn min) value)) (signum (- (funcall fn max) value)))))
    (labels ((frob (x)
	     (if (or (< (abs (- (funcall fn x) value)) *epsilon*)
		     (= x max)
		     (= x min))
		 (return-from invert x)
	       (let ((f (funcall fn x)))
		 (if (= (signum (- f value)) (signum (- (funcall fn min) value)))
		     (setf min x)
		   (setf max x))
		 (frob (+ min (/ (* (- max min) (- value (funcall fn min))) (- (funcall fn max) (funcall fn min)))))))))
      (frob (+ min (/ (* (- max min) (- value (funcall fn min))) (- (funcall fn max) (funcall fn min))))))))