Effects of moderate noise on a limit cycle oscillator: Counterrotation and bistability (Phys. Rev. Lett., 2014)
Noisy limit cycle animation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
</head> | |
<script type="text/x-mathjax-config"> | |
MathJax.Hub.Config({ | |
tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}, | |
tex: {extensions: ["color.js"]}}); | |
</script> | |
<script type="text/javascript" | |
src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_SVG"> | |
</script> | |
<style> | |
body {height: 100%;width: 100%;} | |
#animation { | |
position: absolute; | |
top: 50px; | |
left: 200px; | |
} | |
#svgAxes { | |
position: absolute; | |
top: 50px; | |
left: 200px; | |
stroke: #000; | |
font: 10px sans-serif; | |
} | |
.axis { | |
stroke: none; | |
fill: #000; | |
} | |
.axis line, .axis path { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
#slider { | |
position: absolute; | |
top: 300px; | |
left: 550px; | |
width: 150px; | |
background: none; | |
font: 10px sans-serif; | |
} | |
#sliderLabel { | |
position: absolute; | |
top: 260px; | |
left: 575px; | |
font: 30px serif; | |
} | |
#ylabel { | |
position: absolute; | |
top: 150px; | |
left: 170px; | |
font: 30px serif; | |
} | |
#xlabel { | |
position: absolute; | |
top: 330px; | |
left: 350px; | |
font: 30px serif; | |
} | |
#equations { | |
position: absolute; | |
top: 370px; | |
left: 170px; | |
} | |
</style> | |
<body> | |
<canvas id="animation" width="250" height="250"></canvas> | |
<svg id="svgAxes" width="250" height="250"></svg> | |
<span id="xlabel" touch-action="none"><em>x</em></span> | |
<span id="ylabel" touch-action="none"><em>y</em></span> | |
<span id="sliderLabel">σ = <span id="sliderValue"></span></span> | |
<div style="text-align: center"> | |
<input type="range" id="slider" value="10" min="0" max="50"> | |
</div> | |
<div id="equations"> | |
\[\begin{align} | |
dX &= \left[\gamma\left(1-X^2 - Y^2\right)X - \left(1 - \gamma c\left(1 - \sqrt{X^2 + Y^2}\right)^{2}\right)Y\right]dt + \sigma dW_x \\ | |
dY &= \left[\gamma\left(1-X^2 - Y^2\right)Y + \left(1 - \gamma c\left(1 - \sqrt{X^2 + Y^2}\right)^{2}\right)X\right]dt + \sigma dW_y | |
\end{align}\] | |
</div> | |
<script type="text/javascript" src="http://iop.io/js/vendor/d3.v3.min.js"></script> | |
<script src="lc_anim.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function anim() { | |
//////////////////// | |
//// simulation //// | |
//////////////////// | |
var gamma = 50, | |
c = 25, | |
dt = 0.004, | |
x = 1, | |
y = 0, | |
rn = d3.random.normal(0, Math.sqrt(dt)); | |
function evolve_simulation() { | |
for (var i=0; i<2; i++) { | |
var rho = Math.sqrt(x*x + y*y), | |
r = rho - 1, | |
a = gamma*(1 - rho*rho), | |
b = -gamma*c*r*r + 1; | |
x += (x*a - b*y)*dt + sigma*rn(); | |
y += (y*a + b*x)*dt + sigma*rn(); | |
} | |
} | |
///////////////////////// | |
//// animation setup //// | |
///////////////////////// | |
var width = 250, | |
height = width, | |
mw = 30, | |
cNa = "#F24533", // orange 242,69,51 | |
cK = "#0080FF", // blue 0,128,255 | |
linecolor = d3.interpolateRgb(cK, cNa); | |
var g = d3.select("#animation").node().getContext("2d"); | |
g.fillStyle = "rgba(255, 255, 255, 0.05)"; // for fading curves | |
g.strokeStyle = linecolor(0); | |
g.lineWidth = 4; | |
var svg = d3.select("#svgAxes") | |
// .attr("width", width) | |
// .attr("height", height) | |
.style("margin-bottom", mw + "px") | |
.style("margin-top", mw + "px"), | |
//// limit cycle //// | |
circ_trans = (width - 2*mw)/2 + mw; | |
svg.append("g").attr("transform", "translate(" + mw + ", "+ -mw + ")") | |
.append("circle") | |
.attr("r", (width-2*mw)/2.4) | |
.attr("transform", "translate(" + circ_trans + "," + circ_trans +")") | |
.style("fill", "none").style("opacity", 0.3); | |
//// axes //// | |
scx = d3.scale.linear() | |
.domain([-1.2, 1.2]) | |
.range([mw, width - 1.01*mw]), | |
scy = d3.scale.linear() | |
.domain([-1.2, 1.2]) | |
.range([height - mw, mw]), | |
xyline = d3.svg.line() | |
.x(function(d, i) { return scx(d.x); }) | |
.y(function(d, i) { return scy(d.y); }), | |
svg.append("g").attr("class", "axis") | |
.attr("transform", "translate(" + mw + "," + (height-mw) + ")") | |
.call(d3.svg.axis().scale(scx).orient("bottom").tickValues([-1, 0, 1])); | |
svg.append("g").attr("class", "axis") | |
.attr("transform", "translate(" + mw + "," + (-mw) + ")") | |
.call(d3.svg.axis().scale(scy).orient("left").tickValues([-1, 0, 1])); | |
//// simulation trajectory /// | |
var drawFlag = true, | |
frameRate = 20; | |
d3.timer(function () {if (drawFlag) {draw();}}, frameRate); | |
g.globalCompositeOperation = "source-over"; | |
function draw() { | |
g.fillRect(0, 0, width, height); // fades all existing curves by a set amount determined by fillStyle above | |
g.beginPath(); | |
g.moveTo(scx(x)+mw, scy(y)); | |
for (var i=0; i<5; i++) {evolve_simulation();} | |
g.lineTo(scx(x)+mw, scy(y)); | |
g.stroke(); | |
} | |
//// events //// | |
var slider = document.querySelector("#slider"), | |
sigma = slider.value/100; | |
document.getElementById("sliderValue").innerHTML = sigma.toPrecision(2); | |
slider.addEventListener("input", | |
function () { | |
sigma = slider.value/100; | |
document.getElementById("sliderValue").innerHTML = sigma.toPrecision(2); | |
g.strokeStyle = linecolor(sigma/0.5); | |
}, false); | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment