Home
|
Course Outline
|
Lectures
|
Homework
|
Files
Problem 12.13 on page 391 uses the reptation model of polymer motion to help generate a random statistical sample of polymer configurations. The method has the advantage that it cannot fail, unlike a self-avoiding random walk which can encounter a cul-de-sac.
The following applet, which is generated by the program Reptation.java, implements this reptation enrichment method. The idea is to generate a large number of chains of fixed length N starting from any particular chain. The bond angles are constrained to be +90o or -90o, so one could start from a simple "staircase". However, this program uses a self-avoiding random walk to generate the initial polymer to illustrate the phenomenon of cul-de-sacs. Once the initial configuration is found, the reptation algorithm takes over, and the mean squared head-to-tail distance of the generated chains is measured.
Here is the code which generates this applet:
// Reptation.java
import comphys.Easy;
import comphys.graphics.*;
public class Reptation extends Animation {
int N = 5; // length of polymer chain
int[] xMolecule, yMolecule; // x,y coordinates of molecules in chain
int[] xCopy, yCopy; // to copy polymer
int nPolymers; // number of polymers in sample
double RSquaredSum; // sum of head-to-tail distances squared
int L = 10; // lattice points in each direction
boolean occupied (int x, int y) {
for (int n = 0; n < N; n++)
if (xMolecule[n] == x && yMolecule[n] == y)
return true;
return false;
}
int xPrevious, yPrevious;
int xCurrent, yCurrent;
int xTrial, yTrial;
void trialStep () {
if (xPrevious == xCurrent) { // step right or left
yTrial = yCurrent;
if (Math.random() < 0.5)
xTrial = xCurrent + 1;
else
xTrial = xCurrent - 1;
} else { // step up or down
xTrial = xCurrent;
if (Math.random() < 0.5)
yTrial = yCurrent + 1;
else
yTrial = yCurrent - 1;
}
}
boolean culDeSac () {
if (xPrevious == xCurrent)
return
occupied(xCurrent + 1, yCurrent) &&
occupied(xCurrent - 1, yCurrent);
else
return
occupied(xCurrent, yCurrent + 1) &&
occupied(xCurrent, yCurrent - 1);
}
int nTry; // number of trials made
int nWalk; // number of steps in trial
void randomStep () {
if (nWalk == 0) { // first step in a random direction
switch ( (int)(4 * Math.random()) ) {
case 0: ++xMolecule[1]; break;
case 1: --xMolecule[1]; break;
case 2: ++yMolecule[1]; break;
case 3: --yMolecule[1]; break;
}
nWalk = 1;
return;
}
xCurrent = xMolecule[nWalk];
yCurrent = yMolecule[nWalk];
xPrevious = xMolecule[nWalk - 1];
yPrevious = yMolecule[nWalk - 1];
if (culDeSac()) { // need to start over
initial();
needToClear = true;
return;
}
do {
trialStep();
} while (occupied(xTrial, yTrial));
++nWalk;
xMolecule[nWalk] = xTrial;
yMolecule[nWalk] = yTrial;
}
void initial () {
nPolymers = 0;
RSquaredSum = 0;
if (xMolecule == null || xMolecule.length != N+1) {
xMolecule = new int[N+1];
yMolecule = new int[N+1];
xCopy = new int[N+1];
yCopy = new int[N+1];
}
// store all molecules at center of lattice for convenience
for (int n = 0; n < N; n++)
xMolecule[n] = yMolecule[n] = L / 2;
nWalk = 0;
++nTry;
}
void copy () {
for (int n = 0; n <= N; n++) {
xCopy[n] = xMolecule[n];
yCopy[n] = yMolecule[n];
}
}
void reptate () {
// save a copy in case reptation fails
copy();
// remove tail
for (int n = 0; n < N; n++) {
xMolecule[n] = xMolecule[n+1];
yMolecule[n] = yMolecule[n+1];
}
// head attempts to move
xCurrent = xMolecule[N-1];
yCurrent = yMolecule[N-1];
xPrevious = xMolecule[N-2];
yPrevious = yMolecule[N-2];
trialStep();
// test whether move is allowed
if (!occupied(xTrial, yTrial)) {
// accept new head position
xMolecule[N] = xTrial;
yMolecule[N] = yTrial;
} else {
// interchange head and tail in previous configuration
for (int n = 0; n <= N; n++) {
xMolecule[n] = xCopy[N - n];
yMolecule[n] = yCopy[N - n];
}
}
++nPolymers;
double dx = xMolecule[0] - xMolecule[N];
double dy = yMolecule[0] - yMolecule[N];
RSquaredSum += dx * dx + dy * dy;
moveToCenterOfScreen();
}
void moveToCenterOfScreen () {
// if polymer moves off screen
boolean needToMove = false;
for (int n = 0; n <= N; n++) {
if (xMolecule[n] < 0 || xMolecule[n] > L ||
yMolecule[n] < 0 || yMolecule[n] > L) {
needToMove = true;
break;
}
}
if (needToMove) {
int xShift = xMolecule[N / 2] - L / 2;
int yShift = yMolecule[N / 2] - L / 2;
for (int n = 0; n <= N; n++) {
xMolecule[n] -= xShift;
yMolecule[n] -= yShift;
}
}
}
boolean needToClear; // clear screen if true
boolean initializing; // true while finding first polymer
boolean reptating; // true while reptating
class Walk extends Plot {
public void paint () {
if (needToClear) {
clear();
needToClear = false;
setWindow(0, L, 0, L);
setColor("blue");
for (int x = 0; x < L; x++)
for (int y = 0; y < L; y++)
plotPoint(x, y);
}
setColor("blue");
boolean toggle = true;
for (int n = 0; n < nWalk; n++) {
if (reptating) {
if (toggle)
setColor("orange");
else
setColor("black");
toggle = !toggle;
}
plotLine(xMolecule[n + 1], yMolecule[n + 1],
xMolecule[n], yMolecule[n]);
}
if (reptating) {
setColor("red");
double r = 0.2;
floodCircle(xMolecule[N] - r, xMolecule[N] + r,
yMolecule[N] - r, yMolecule[N] + r);
}
}
}
class Output extends Plot {
Output () {
setSize(400, 30);
}
public void paint () {
setWindow(0, 12, 0, 3);
clear();
if (reptating) {
setColor("magenta");
plotString("Reptating ...", 1, 1);
plotStringCenter("Polymers: " + nPolymers, 6, 1);
double RSquaredAverage = RSquaredSum;
if (nPolymers > 0)
RSquaredAverage /= nPolymers;
plotStringLeft(" = " + Easy.format(RSquaredAverage, 4),
11, 1);
} else if (initializing) {
setColor("red");
plotString("Initializing ...", 1, 1);
plotStringCenter("Trial No: " + nTry, 6, 1);
plotStringLeft("N = " + nWalk, 11, 1);
} else {
setColor("green");
plotStringCenter("Polymer Reptation Simulation", 6, 1);
}
}
}
Walk walk;
Output output;
Reader NReader, LReader;
public void init () {
initial();
needToClear = true;
add(walk = new Walk());
add(output = new Output());
add(NReader = new Reader("N = ", N));
add(LReader = new Reader("L = ", L));
addControlPanel();
}
public void step () {
if (nWalk < N) {
initializing = true;
randomStep();
} else {
needToClear = reptating = true;
reptate();
}
walk.repaint();
output.repaint();
}
public void reset () {
needToClear = true;
reptating = initializing = false;
N = NReader.readInt();
L = LReader.readInt();
nTry = 0;
initial();
walk.repaint();
output.repaint();
}
public static void main (String[] args) {
Reptation reptation = new Reptation();
reptation.frame("Polymer Reptation Simulation", 500, 600);
}
}