Here is the code for the algorithm as described in the paper. It is in ANSI standard C. Available files:
perc.c:
| complete source code for the algorithm |
rnglong.c,
rnglong.h:
| source code for a suitable random number generator to go with it |
Makefile:
| a Makefile suitable for compiling the program on Unix-type systems (including Linux). |
First we set up some constants and global variables:
#include stdlib.h #include stdio.h #define L 128 /* Linear dimension */ #define N (L*L) #define EMPTY (-N-1) int ptr[N]; /* Array of pointers */ int nn[N][4]; /* Nearest neighbors */ int order[N]; /* Occupation order */
Sites are indexed with a single signed integer label for speed, taking values from 0 to N-1. Note that on computers which represent integers in 32 bits, this program can, for this reason, only be used for lattices of up to 231, or about 2 billion sites. While this is adequate for most purposes, longer labels will be needed if you wish to study larger lattices.
The array ptr[] serves triple duty: for non-root occupied
sites it contains the label for the site's parent in the tree (the
"pointer"); root sites are recognized by a negative value of
ptr[], and that value is equal to minus the size of the
cluster; for unoccupied sites ptr[] takes the value
EMPTY.
Next we set up the array nn[][] which contains a list of the
nearest neighbors of each site. Only this array need be changed in order
for the program to work with a lattice of different topology.
void boundaries()
{
int i;
for (i=0; iN; i++) {
nn[i][0] = (i+1)%N;
nn[i][1] = (i+N-1)%N;
nn[i][2] = (i+L)%N;
nn[i][3] = (i+N-L)%N;
if (i%L==0) nn[i][1] = i+L-1;
if ((i+1)%L==0) nn[i][0] = i-L+1;
}
}
Now we generate the random order in which the sites will be occupied, by randomly permuting the integers from 0 to N-1:
void permutation()
{
int i,j;
int temp;
for (i=0; iN; i++) order[i] = i;
for (i=0; iN; i++) {
j = i + (N-i)*drand();
temp = order[i];
order[i] = order[j];
order[j] = temp;
}
}
Here the function drand() generates a random double precision
floating point number between 0 and 1. Many people will have such a
function already to hand. For those who don't, a suitable one is supplied
here and here.
We also define a function which performs the "find" operation, returning the label of the root site of a cluster, as well as path compression. The version we use is recursive, as described in the paper:
int findroot(int i)
{
if (ptr[i]0) return i;
return ptr[i] = findroot(ptr[i]);
}
The code to perform the actual algorithm is quite brief. It works exactly
as described in the paper. Sites are occupied in the order specified by
the array order[]. The function findroot() is
called to find the roots of each of the adjacent sites. If amalgamation is
needed, it is performed in a weighted fashion, smaller clusters being added
to larger (bearing in mind that the value of ptr[] for the
root nodes is minus the size of the corresponding cluster).
void percolate()
{
int i,j;
int s1,s2;
int r1,r2;
int big=0;
for (i=0; iN; i++) ptr[i] = EMPTY;
for (i=0; iN; i++) {
r1 = s1 = order[i];
ptr[s1] = -1;
for (j=0; j4 j++) {
s2 = nn[s1][j];
if (ptr[s2]!=EMPTY) {
r2 = findroot(s2);
if (r2!=r1) {
if (ptr[r1]>ptr[r2]) {
ptr[r2] += ptr[r1];
ptr[r1] = r2;
r1 = r2;
} else {
ptr[r1] += ptr[r2];
ptr[r2] = r1;
}
if (-ptr[r1]>big) big = -ptr[r1];
}
}
}
printf("%i %i\n",i+1,big);
}
}
The main program is now simple:
main()
{
boundaries();
permutation();
percolate();
}
Last modified: January 19, 2001
Mark Newman