Skip to content

Instantly share code, notes, and snippets.

@thejh
Created March 5, 2012 23:33
Show Gist options
  • Save thejh/1982072 to your computer and use it in GitHub Desktop.
Save thejh/1982072 to your computer and use it in GitHub Desktop.
Runge-Kutta in Coco
<!DOCTYPE html>
<html>
<head>
<!-- Der Deutsch-Englisch-Mischmasch tut mir leid, aber ich bin es gewohnt, auf Englisch zu programmieren, und kenne viele Fachbegriffe nicht auf English...
und dann wird mein Code zu einem Mischmasch, weil ich die ganze Zeit umschalte.
-->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Kurvenverläufe von Lotka-Volterra-Gleichungen malen</title>
<script type="coco">
# die Differentialfunktionen von Räuber und Beute
# Argument 1: n1 und n2, Argument 2: Parameter
beutedifferenz = ({n1, n2}, {epsilon1, gamma1}) -> n1 * (epsilon1 - gamma1*n2)
räuberdifferenz = ({n1, n2}, {epsilon2, gamma2}) -> -n2 * (epsilon2 - gamma2*n1)
# Zahl aus einem Eingabefeld auslesen
getnumber = (name) ->
parseFloat (document.getElementById name).value
# Methode, um die Grafik neu zu zeichnen
window.redraw = !->
t = 0
# Werte aus den HTML-Eingabefeldern auslesen
xmax = getnumber \xmax
stepsperpixel = 100
stepsize = (xmax / 600) / stepsperpixel
yscale = 200 / (getnumber \ymax)
n1 = getnumber \n1_0
n2 = getnumber \n2_0
# Parameter in einem Objekt speichern
parameters =
epsilon1: getnumber \epsilon1
epsilon2: getnumber \epsilon2
gamma1: getnumber \gamma1
gamma2: getnumber \gamma2
# Malbereich (canvas) initialisieren
context = (document.getElementById \canvas).getContext \2d
context.clearRect 0, 0, 600, 200 # transparent/weiß machen
# und jetzt das runge-kutta-verfahren in der schleife anwenden...
while t < 600
# alte Werte zwischenspeichern, damit Linien zwischen alten und neuen Punkten gemacht werden können
oldn1 = n1
oldn2 = n2
for i from 1 to stepsperpixel
k1_beute = stepsize * beutedifferenz {n1: n1, n2: n2}, parameters
k1_räuber = stepsize * räuberdifferenz {n1: n1, n2: n2}, parameters
k2_beute = stepsize * beutedifferenz {n1: n1 + k1_beute/2, n2: n2 + k1_räuber/2}, parameters
k2_räuber = stepsize * räuberdifferenz {n1: n1 + k1_beute/2, n2: n2 + k1_räuber/2}, parameters
k3_beute = stepsize * beutedifferenz {n1: n1 + k2_beute/2, n2: n2 + k2_räuber/2}, parameters
k3_räuber = stepsize * räuberdifferenz {n1: n1 + k2_beute/2, n2: n2 + k2_räuber/2}, parameters
k4_beute = stepsize * beutedifferenz {n1: n1 + k3_beute, n2: n2 + k3_räuber}, parameters
k4_räuber = stepsize * räuberdifferenz {n1: n1 + k3_beute, n2: n2 + k3_räuber}, parameters
n1 += (k1_beute + 2*k2_beute + 2*k3_beute + k4_beute ) / 6
n2 += (k1_räuber + 2*k2_räuber + 2*k3_räuber + k4_räuber) / 6
t++
# diesen Schritt malen
# jedesmal Y invertieren - canvas zählt von oben!
context.strokeStyle = "green"
context.beginPath!
context.moveTo t-1, 200 - Math.round oldn1*yscale
context.lineTo t, 200 - Math.round n1*yscale
context.stroke!
context.strokeStyle = "orange"
context.beginPath!
context.moveTo t-1, 200 - Math.round oldn2*yscale
context.lineTo t, 200 - Math.round n2*yscale
context.stroke!
# Daten in die Eingabefelder laden und neu zeichnen
window.preset = (data) ->
for key, value in data
(document.getElementById key).value = value
redraw!
console.log "loaded!"
</script>
<script src="coco.js"></script>
</head>
<body>
<div>
<!-- Ausgabebereich -->
<canvas id="canvas" width="600" height="200" style="border: 1px solid black">Wenn man das hier sieht, ist der Browser zu alt für das canvas-Tag</canvas>
</div>
<div>
<!-- Eingabefelder -->
Anfangsgröße der Beutepopulation: <input id="n1_0" value="">
<br>
Anfangsgröße der Räuberpopulation: <input id="n2_0" value="">
<br>
Reproduktionsrate der Beutepopulation: <input id="epsilon1" value="">
<br>
Sterberate der Beutepopulation durch Räuber: <input id="gamma1" value="">
<br>
Reproduktionsrate der Räuber pro Beutetier: <input id="gamma2" value="">
<br>
Sterberate der Räuber bei Beutemangel: <input id="epsilon2" value="">
<br>
t-Maximum: <input id="xmax" value="">
<br>
Y-Maximum: <input id="ymax" value="">
<br>
<button onclick="redraw()">
OK
</button>
<p>
Dies sind einige nett aussehende Voreinstellungen:
<button onclick="preset({n1_0: 100, n2_0: 10, epsilon1: 0.01, gamma1: 0.0001, gamma2: 0.001, epsilon2: 0.03, xmax: 10000, ymax: 1000})">stabil</button>
</p>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment