diff --git a/contents/verlet_integration/code/clisp/verlet.lisp b/contents/verlet_integration/code/clisp/verlet.lisp new file mode 100644 index 000000000..726b1f1c6 --- /dev/null +++ b/contents/verlet_integration/code/clisp/verlet.lisp @@ -0,0 +1,45 @@ +;;;; Verlet integration implementation in Common Lisp + +(defun verlet (pos acc dt) + "Integrates Newton's equation for motion while pos > 0 using Verlet integration." + (loop + with prev-pos = pos + for time = 0 then (incf time dt) + while (> pos 0) + ;; The starting speed is assumed to be zero. + do (psetf + pos (+ (* pos 2) (- prev-pos) (* acc dt dt)) + prev-pos pos) + finally (return time))) + +(defun stormer-verlet (pos acc dt) + "Integrates Newton's equation for motion while pos > 0 using the Stormer-Verlet method." + (loop + with prev-pos = pos + for time = 0 then (incf time dt) + for vel = 0 then (incf vel (* acc dt)) + while (> pos 0) + ;; Variables are changed simultaneously by 'psetf', so there's no need for a temporary variable. + do (psetf + pos (+ (* pos 2) (- prev-pos) (* acc dt dt)) + prev-pos pos) + finally (return (list time vel)))) + +(defun velocity-verlet (pos acc dt) + "Integrates Newton's equation for motion while pos > 0 using the velocity in calculations." + (loop + for time = 0 then (incf time dt) + for vel = 0 then (incf vel (* acc dt)) + for p = pos then (incf p (+ (* vel dt) (* 0.5 acc dt dt))) + while (> p 0) + finally (return (list time vel)))) + +(format T "Time for Verlet integration: ~d~%" (verlet 5 -10 0.01)) + +(defvar stormer-verlet-result (stormer-verlet 5 -10 0.01)) +(format T "Time for Stormer Verlet integration is: ~d~%" (first stormer-verlet-result)) +(format T "Velocity for Stormer Verlet integration is: ~d~%" (second stormer-verlet-result)) + +(defvar velocity-verlet-result (velocity-verlet 5 -10 0.01)) +(format T "Time for velocity Verlet integration is: ~d~%" (first velocity-verlet-result)) +(format T "Velocity for velocity Verlet integration is: ~d~%" (second velocity-verlet-result)) diff --git a/contents/verlet_integration/verlet_integration.md b/contents/verlet_integration/verlet_integration.md index 62d94de74..6183db0ed 100644 --- a/contents/verlet_integration/verlet_integration.md +++ b/contents/verlet_integration/verlet_integration.md @@ -69,6 +69,8 @@ Unfortunately, this has not yet been implemented in LabVIEW, so here's Julia cod [import:3-15, lang:"kotlin"](code/kotlin/verlet.kt) {% sample lang="nim" %} [import:1-14, lang:"nim"](code/nim/verlet.nim) +{% sample lang="lisp" %} +[import:3-13, lang:"lisp"](code/clisp/verlet.lisp) {% endmethod %} Now, obviously this poses a problem; what if we want to calculate a term that requires velocity, like the kinetic energy, $$\frac{1}{2}mv^2$$? In this case, we certainly cannot get rid of the velocity! Well, we can find the velocity to $$\mathcal{O}(\Delta t^2)$$ accuracy by using the Stormer-Verlet method, which is the same as before, but we calculate velocity like so @@ -125,6 +127,8 @@ Unfortunately, this has not yet been implemented in LabVIEW, so here's Julia cod [import:17-30, lang:"kotlin"](code/kotlin/verlet.kt) {% sample lang="nim" %} [import:16-32, lang:"nim"](code/nim/verlet.nim) +{% sample lang="lisp" %} +[import:15-26, lang:"lisp"](code/clisp/verlet.lisp) {% endmethod %} @@ -195,6 +199,8 @@ Unfortunately, this has not yet been implemented in LabVIEW, so here's Julia cod [import:32-42, lang:"kotlin"](code/kotlin/verlet.kt) {% sample lang="nim" %} [import:34-45, lang:"nim"](code/nim/verlet.nim) +{% sample lang="lisp" %} +[import:28-35, lang:"lisp"](code/clisp/verlet.lisp) {% endmethod %} Even though this method is more widely used than the simple Verlet method mentioned above, it unforunately has an error term of $$\mathcal{O}(\Delta t^2)$$, which is two orders of magnitude worse. That said, if you want to have a simulaton with many objects that depend on one another --- like a gravity simulation --- the Velocity Verlet algorithm is a handy choice; however, you may have to play further tricks to allow everything to scale appropriately. These types of simulatons are sometimes called *n-body* simulations and one such trick is the Barnes-Hut algorithm, which cuts the complexity of n-body simulations from $$\sim \mathcal{O}(n^2)$$ to $$\sim \mathcal{O}(n\log(n))$$. @@ -256,6 +262,8 @@ Submitted by P. Mekhail [import, lang:"kotlin"](code/kotlin/verlet.kt) {% sample lang="nim" %} [import, lang="nim"](code/nim/verlet.nim) +{% sample lang="lisp" %} +[import, lang:"lisp"](code/clisp/verlet.lisp) {% endmethod %}