#include #include /* GT 1D sandpile plus own modifications */ void sgenrand(); double genrand(); main(int argc, char **argv) { int Nsteps,L,plot,mode,seed; int i,j,istep,irand,ntopplesteps,ntopplemax,ntopplelast; int *h,*hprev,*topplestat,*tleft,*tright; int hsum,hmax; int istepprint=10000,firstprint=1; FILE *fp; if (argc < 6) { printf("Usage: sandpile_rand Nsteps L plot mode seed\n"); printf("\n"); printf(" mode: 0 Add grain randomly, 1 add in middle\n"); exit(0); } sscanf(argv[1],"%d",&Nsteps); sscanf(argv[2],"%d",&L); sscanf(argv[3],"%d",&plot); sscanf(argv[4],"%d",&mode); sscanf(argv[5],"%d",&seed); printf("Args were %d %d %d %d\n",Nsteps,L,plot,mode); h=(int *) malloc(sizeof(int)*(L+2)); hprev=(int *) malloc(sizeof(int)*(L+2)); topplestat=(int *) malloc(sizeof(int)*L/2*(L+2)); tleft=(int *) malloc(sizeof(int)*(L+2)); tright=(int *) malloc(sizeof(int)*(L+2)); sgenrand(seed); ntopplemax=0; for(i=1;i<=L+1;i++) { h[i]=0; topplestat[i]=0; } for(istep=1;istep<=Nsteps;istep++) { if (mode==0) { /* Add grain */ irand=(int)(genrand()*L)+1; h[irand]++; } else if (mode==1) { /* Add grain in middle only */ irand=(int)(L/2); h[irand]++; } for(i=1;i<=L+1;i++) hprev[i]=h[i]; /****** Start of one toppling loop step *****/ ntopplelast=1; /* Loop as long as anything can be toppled */ ntopplesteps=0; while (ntopplelast>0) { /* Find grains to be toppled */ for(i=1;i<=L;i++) { tright[i]=0; tleft[i]=0; if (h[i] - h[i+1] > 2) tright[i]=1; if (h[i] - h[i-1] > 2) tleft[i]=1; if (tright[i]==1 && tleft[i]==1) { /* But if only 3 grains too much, choose */ /* topple direction at random */ if (h[i] - h[i+1]==3 && h[i] - h[i-1]==3) { tright[i]=0; tleft[i]=0; if (genrand()>=0.5) tright[i]=1; else tleft[i]=1; } } } /* Topple grains */ ntopplelast=0; for(i=1;i<=L;i++) { if (tright[i] == 1) { h[i]-=2; h[i+1]++; h[i+2]++; ntopplelast+=2; } if (tleft[i] == 1) { h[i]-=2; h[i-1]++; h[i-2]++; ntopplelast+=2; } /* print i,h[i] */ } h[0]=0; h[-1]=0; h[L+1]=0; h[L+2]=0; ntopplesteps+=ntopplelast; } /****** End of one toppling loop step *****/ if (istep > L*L) { if (firstprint) { printf("*********** Now starting to collect statistics *********\n"); firstprint=0; } /* Collect statistics of of how many grains were toppled during this step */ if (ntopplesteps > L/2*(L+2)) { printf("Error: ntopple array size too small, ntopple %d\n",ntopplesteps); exit(1); } topplestat[ntopplesteps]++; if (ntopplesteps > ntopplemax) ntopplemax=ntopplesteps; } if (plot==1 || (istep%istepprint==0) ) { /* Reduce printing interval for long runs */ if (istep > istepprint*100) istepprint=istepprint*10; /* Plot results (ascii graphics) */ hmax=0; for(i=1;i<=L;i++) { if (hprev[i] > hmax) hmax=hprev[i]; } for(i=hmax;i>=1;i--) { for(j=1;j<=L;j++) { if (hprev[j]>=i) printf("X"); else printf(" "); } printf("\n"); } for(i=1;i<=L/2;i++) printf("- "); printf("\n"); hmax=0; hsum=0; for(i=1;i<=L;i++) { hsum+=h[i]; if (h[i] > hmax) hmax=h[i]; } for(i=hmax;i>=1;i--) { for(j=1;j<=L;j++) { if (h[j]>=i) printf("X"); else printf(" "); } printf("\n"); } for(i=1;i<=L;i++) printf("-"); printf(" nstep %d ntopple %d ntopplemax %d hsum %d\n\n\n",istep,ntopplesteps,ntopplemax,hsum); if (firstprint==0 && istep%(istepprint*10)==0) { fp=fopen("topplestat.dat","w"); for(i=0;i<=ntopplemax+1;i+=2) fprintf(fp,"%d %d\n",i,topplestat[i]); fclose(fp); } } } } /* A C-program for MT19937: Real number version */ /* genrand() generates one pseudorandom real number (double) */ /* which is uniformly distributed on [0,1]-interval, for each */ /* call. sgenrand(seed) set initial values to the working area */ /* of 624 words. Before genrand(), sgenrand(seed) must be */ /* called once. (seed is any 32-bit integer except for 0). */ /* Integer generator is obtained by modifying two lines. */ /* Coded by Takuji Nishimura, considering the suggestions by */ /* Topher Cooper and Marc Rieffel in July-Aug. 1997. */ /* This library is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Library General Public */ /* License as published by the Free Software Foundation; either */ /* version 2 of the License, or (at your option) any later */ /* version. */ /* This library is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ /* See the GNU Library General Public License for more details. */ /* You should have received a copy of the GNU Library General */ /* Public License along with this library; if not, write to the */ /* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */ /* 02111-1307 USA */ /* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. */ /* Any feedback is very welcome. For any question, comments, */ /* see http://www.math.keio.ac.jp/matumoto/emt.html or email */ /* matumoto@math.keio.ac.jp */ #include /* Period parameters */ #define N 624 #define M 397 #define MATRIX_A 0x9908b0df /* constant vector a */ #define UPPER_MASK 0x80000000 /* most significant w-r bits */ #define LOWER_MASK 0x7fffffff /* least significant r bits */ /* Tempering parameters */ #define TEMPERING_MASK_B 0x9d2c5680 #define TEMPERING_MASK_C 0xefc60000 #define TEMPERING_SHIFT_U(y) (y >> 11) #define TEMPERING_SHIFT_S(y) (y << 7) #define TEMPERING_SHIFT_T(y) (y << 15) #define TEMPERING_SHIFT_L(y) (y >> 18) static unsigned long mt[N]; /* the array for the state vector */ static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */ /* initializing the array with a NONZERO seed */ void sgenrand(seed) unsigned long seed; { /* setting initial seeds to mt[N] using */ /* the generator Line 25 of Table 1 in */ /* [KNUTH 1981, The Art of Computer Programming */ /* Vol. 2 (2nd Ed.), pp102] */ mt[0]= seed & 0xffffffff; for (mti=1; mti= N) { /* generate N words at one time */ int kk; if (mti == N+1) /* if sgenrand() has not been called, */ sgenrand(4357); /* a default initial seed is used */ for (kk=0;kk> 1) ^ mag01[y & 0x1]; } for (;kk> 1) ^ mag01[y & 0x1]; } y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= TEMPERING_SHIFT_U(y); y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B; y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C; y ^= TEMPERING_SHIFT_L(y); return ( (double)y / (unsigned long)0xffffffff ); /* reals */ /* return y; */ /* for integer generation */ }