Skip to content

Instantly share code, notes, and snippets.

@mikeskaug
Last active May 26, 2017 20:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikeskaug/8e5bb8591655dcab6a11794d608f245a to your computer and use it in GitHub Desktop.
Save mikeskaug/8e5bb8591655dcab6a11794d608f245a to your computer and use it in GitHub Desktop.
Polymer dynamics

A simulation of polymer dynamics using d3.

The physics are not quite right, namely the bond lengths should be much more rigid, but it illustrates the basic physical picture of random thermal fluctuations in the polymer chain.

<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.8.0/d3.min.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<script src="index.js"></script>
</body>
const width = window.innerWidth;
const height = window.innerHeight;
const originX = width / 2;
const originY = height / 2;
const monomerRadius = 20;
const bondLength = monomerRadius * 2.2;
const monomers = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5].map(xPos => {
return {
x: originX + (xPos * bondLength),
y: originY,
vx: 0,
vy: 0,
r: monomerRadius
}
});
const bonds = monomers.slice(0, monomers.length - 2).map((mer, index) => {
return {
source: index,
target: index + 1
}
});
const bondForce = d3.forceLink(bonds)
.distance(bondLength)
.iterations(20);
const polymerSim = d3.forceSimulation()
.nodes(monomers)
.force('link', bondForce)
.force('collide', d3.forceCollide(monomerRadius))
.alphaDecay(0.1);
const line = d3.line()
.x(d => d.x)
.y(d => d.y);
const svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("path");
const path = svg.selectAll("path").data(monomers);
const balls = svg.selectAll('circle')
.data(monomers)
.enter().append('circle')
.attr('r', monomerRadius)
.attr('cx', d => d.x)
.attr('cy', d => d.y);
function thermalize () {
let updatedMonomers = polymerSim.nodes().map(node => {
return {
x: node.x + d3.randomNormal(0, 0.5)(),
y: node.y + d3.randomNormal(0, 0.5)(),
vx: node.vx ,
vy: node.vy ,
r: node.r
};
})
polymerSim.nodes(updatedMonomers);
balls.data(updatedMonomers)
.attr('cx', d => d.x)
.attr('cy', d => d.y);
path.attr("d", d => line(updatedMonomers));
};
setInterval(() => {
polymerSim.stop();
thermalize();
polymerSim.tick();
polymerSim.restart();
}, 100);
body {
margin: 0;
text-align: center;
font-family: sans-serif;
font-size: 14px;
}
path {
stroke: rgb(70, 70, 70);
stroke-linejoin: round;
stroke-width: 10px;
fill: none;
}
circle {
fill: rgb(70, 70, 70);
stroke: none;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment