Skip to content

Instantly share code, notes, and snippets.

@bellbind
Last active July 11, 2016 17:02
Show Gist options
  • Save bellbind/c5bf26f57871268c7a26 to your computer and use it in GitHub Desktop.
Save bellbind/c5bf26f57871268c7a26 to your computer and use it in GitHub Desktop.
[javascript]Simulation of SYNC (Kuramoto model)
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script>
window.addEventListener("load", function () {
"use strict";
var canvas = document.createElement("canvas");
document.body.appendChild(canvas);
canvas.width = canvas.height = 600;
var c2d = canvas.getContext("2d");
var newNodes = function () {
var nodes = [];
for (var x = 0; x < 10; x++) {
for (var y = 0; y < 10; y++) {
nodes.push({phase: Math.random() * Math.PI * 2,
freq: 0.05 + Math.random() * 0.05});
}
}
return nodes;
};
var draw = function (nodes) {
c2d.clearRect(0, 0, 600, 600);
for (var x = 0; x < 10; x++) {
for (var y = 0; y < 10; y++) {
var node = nodes[x * 10 + y];
c2d.save();
c2d.translate(30 + x * 60, 30 + y * 60);
c2d.beginPath();
var r = 15 + 15 * Math.sin(node.phase)
c2d.arc(0, 0, r, 0, Math.PI * 2, false);
c2d.closePath();
c2d.fill();
c2d.restore();
}
}
};
var eular = function (dxdt, x0, t0, h, n) {
var x = x0, t = t0;
for (var i = 0; i < n; i++) {
var dx = dxdt(t, x);
var x_ = x + h * dx;
var dx_ = dxdt(t + h, x_);
x = x + h * (dx + dx_) / 2;
t = t + h;
}
return x;
};
// Kuramoto model
// http://en.wikipedia.org/wiki/Kuramoto_model
var syncNext = function (nodes, K) {
var nexts = [];
var sum = nodes.reduce(function (s, node) {
s.sin += Math.sin(node.phase);
s.cos += Math.cos(node.phase);
return s;
}, {sin:0, cos: 0});
sum.sin /= nodes.length;
sum.cos /= nodes.length;
var r = Math.sqrt(Math.pow(sum.sin, 2) + Math.pow(sum.cos, 2));
var psi = Math.atan2(sum.sin, sum.cos);
for (var x = 0; x < 10; x++) {
for (var y = 0; y < 10; y++) {
var node = nodes[x * 10 + y];
//var dphase = node.freq + K * r * Math.sin(psi - node.phase);
//var nphase = node.phase + dphase;
var dpdt = function (t, phase) {
return node.freq + K * r * Math.sin(psi - phase);
};
var nphase = eular(dpdt, node.phase, 0, 1 / 10, 10);
nexts.push({phase: nphase, freq: node.freq});
}
}
return nexts;
};
var K = 3; // K >= 0 (1 = sync)
var current = newNodes();
draw(current);
var id = setInterval(function () {
current = syncNext(current, K);
draw(current);
}, 100);
document.getElementById("set").addEventListener("click", function () {
K = parseFloat(document.getElementById("K").value);
}, false);
document.getElementById("reset").addEventListener("click", function () {
K = parseFloat(document.getElementById("K").value);
current = newNodes();
}, false);
}, false);
</script>
</head>
<body>
<div>K: <input id="K" value="3" type="number" min="0" step="0.1">
<button id="set">set</button><button id="reset">reset</button></div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment