double PartialOmega(int k0, double *r, int k) { int i, k1, g, g2, i0, i1, i2, i3; double a, b, c, x; x = 0.0; for (i = 0; i <= k; i++) { k1 = k0 + i*2 - k; a = 2.0*(2.0*k0+1.0)*(2.0*k1+1.0); g2 = k0 + k1 + k; g = g2/2; i0 = g2 - 2*k0; i1 = g2 - 2*k1; i2 = g2 - 2*k; if (i2 < 0) i2 = 0; i3 = g2 + 1; b = LnFactorial(i0)+LnFactorial(i1)+LnFactorial(i2)-LnFactorial(i3); i0 = g - k0; i1 = g - k1; i2 = g - k; if (i2 < 0) i2 = 0; c = LnFactorial(g)-LnFactorial(i0)-LnFactorial(i1)-LnFactorial(i2); b += 2.0*c; b = exp(b); x += a*b*r[i]*r[i]; } return x; }
/* ** Wigner d-matrix <jm|exp(-iJ_y*a)|jn> ** j2 = j*2, m2 = m*2, n2 = n*2 */ double WignerDMatrix(double a, int j2, int m2, int n2) { double b, c, ca, sa, x; int k, kmin, kmax; a *= 0.5; kmin = Max(0, (m2+n2)/2); kmax = Min((j2+m2)/2, (j2+n2)/2); ca = cos(a); sa = sin(a); x = 0.0; for (k = kmin; k <= kmax; k++) { b = pow(ca, (2*k-(m2+n2)/2)); b *= pow(sa, (j2+(m2+n2)/2-2*k)); c = LnFactorial(k); c += LnFactorial((j2+m2)/2-k); c += LnFactorial((j2+n2)/2-k); c += LnFactorial(k-(m2+n2)/2); b /= exp(c); if (IsOdd(k)) b = -b; x += b; } c = LnFactorial((j2+m2)/2); c += LnFactorial((j2-m2)/2); c += LnFactorial((j2+n2)/2); c += LnFactorial((j2-n2)/2); c = exp(0.5*c); if (IsOdd((j2+m2)/2)) c = -c; x *= c; return x; }
// divide N particles among p compartments int main(void) // takes in no parameters { int i,j,k,l,index; int P,N,Ncycle; double Distribution[MAX_COMPARTMENTS][MAX_PARTICLES]; //2D Array: what are the brackets doing here? Okay most likely they are to define the dimensionality of the array. int NumInComp[MAX_COMPARTMENTS]; //1D Array: declaring number of particles in compartment FILE *FilePtr; //created sufficient memory for FilePtr // initialize the random number generator with the system time InitializeRandomNumberGenerator(time(0l)); //most likely a function located in ran_uniform.h; I think time(01) is supposed to be the seed value for the generator // read the input parameters printf("Number of Particles N? "); fscanf(stdin,"%d",&N); //I REALLY DON'T Understand what fscanf is doing in this situation printf("Number of Compartments p? "); fscanf(stdin,"%d",&P); printf("Number of Cycles (x %d)? ",CycleMultiplication); fscanf(stdin,"%d",&Ncycle); if(P<2||P>MAX_COMPARTMENTS||N<2||N>MAX_PARTICLES) { printf("Error in input parameters\n"); exit(1); //what does exit do here (and what is the 1 for?) } // initialize: So you have to make sure every entry is zero? What is the default setting? for(i=0;i<N;i++) { for(j=0;j<P;j++) { Distribution[j][i]=0.0; NumInComp[j]=0; } } // loop over all cycles for(i=0;i<Ncycle;i++) for(k=0;k<CycleMultiplication;k++) { // Distribute particles over the compartments: // Loop over all particles, pick a random compartment, and add // a particle to it. // A random number in the interval [0,1> can be generated using // RandomNumber(). // NumInComp[index] = number of particles in compartment 'index'. // start modification for(l=0;l<N;l++) { index = round(RandomNumber()*(P)); NumInComp[index] += 1; } // end modification // make a histogram for(j=0;j<P;j++) { Distribution[j][NumInComp[j]]+=1.0; NumInComp[j]=0; } } // Write Results FilePtr=fopen("results.dat","w"); for(j=0;j<P;j++) { for(i=0;i<N;i++) { if(Distribution[j][i]>0.0) Distribution[j][i]/=(double)Ncycle*CycleMultiplication; fprintf(FilePtr,"%d %f\n",i,Distribution[j][i]); } fprintf(FilePtr,"\n"); } fclose(FilePtr); // write analytical distribution FilePtr=fopen("analytical.dat","w"); for(j=0;j<N;j++) { fprintf(FilePtr,"%d %f\n",j,exp(LnFactorial(N)-LnFactorial(j)- LnFactorial(N-j)-j*log(P)-(N-j)*log(P/((double)(P-1))))); } fclose(FilePtr); return 0; }
/* ** FUNCTION: W6j. ** PURPOSE: calculate the 6j symbol. ** INPUT: {int j1}, ** angular momentum. ** {int j2}, ** angular momentum. ** {int j3}, ** angular momentum. ** {int i1}, ** angular momentum. ** {int i2}, ** angular momentum. ** {int i3}, ** angular momentum. ** RETURN: {double}, ** 6j symbol. ** SIDE EFFECT: ** NOTE: */ double W6j(int j1, int j2, int j3, int i1, int i2, int i3) { int n1, n2, n3, n4, n5, n6, n7, k, kmin, kmax, ic, ki; double r, a; #ifdef PERFORM_STATISTICS clock_t start, stop; start = clock(); #endif if (!(Triangle(j1, j2, j3) && Triangle(j1, i2, i3) && Triangle(i1, j2, i3) && Triangle(i1, i2, j3))) return 0.0; n1 = (j1 + j2 + j3) / 2; n2 = (i2 + i1 + j3) / 2; n3 = (j1 + i2 + i3) / 2; n4 = (j2 + i1 + i3) / 2; n5 = (j1 + j2 + i2 + i1) / 2; n6 = (j1 + i1 + j3 + i3) / 2; n7 = (j2 + i2 + j3 + i3) / 2; kmin = Max(n1, n2); kmin = Max(kmin, n3); kmin = Max(kmin, n4) + 1; kmax = Min(n5, n6); kmax = Min(kmax, n7) + 1; r = 1.0; ic = 0; for (k = kmin + 1; k <= kmax; k++) { ki = kmax -ic; r = 1.0 - (r * ki * (n5-ki+2.0) * (n6-ki+2.0) * (n7-ki+2.0))/ ((ki-1.0-n1) * (ki-1.0-n2) * (ki-1.0-n3) * (ki - 1.0 - n4)); ic++; } a = (LnFactorial(kmin) - LnFactorial(kmin-n1-1) - LnFactorial(kmin-n2-1) - LnFactorial(kmin-n3-1) - LnFactorial(kmin-n4-1) - LnFactorial(n5+1-kmin) - LnFactorial(n6+1-kmin) - LnFactorial(n7+1-kmin)) + ((LnFactorial(n1-j1) + LnFactorial(n1-j2) + LnFactorial(n1-j3) - LnFactorial(n1+1) + LnFactorial(n2-i2) + LnFactorial(n2-i1) + LnFactorial(n2-j3) - LnFactorial(n2+1) + LnFactorial(n3-j1) + LnFactorial(n3-i2) + LnFactorial(n3-i3) - LnFactorial(n3+1) + LnFactorial(n4-j2) + LnFactorial(n4-i1) + LnFactorial(n4-i3) - LnFactorial(n4+1))/2.0); r = r * exp(a); if (IsEven(n5+kmin)) r = -r; if (IsOdd(((j1+j2+i1+i2)/2))) r = -r; #ifdef PERFORM_STATISTICS stop = clock(); timing.w6j += stop - start; #endif return r; }
/* ** FUNCTION: W3j. ** PURPOSE: calculate the Wigner 3j symbol. ** INPUT: {int j1}, ** angular momentum. ** {int j2}, ** angular momentum. ** {int j3}, ** angular momentum. ** {int m1}, ** projection of j1. ** {int m2}, ** projection of j2. ** {int m3}, ** projection of j3. ** RETURN: {double}, ** 3j coefficients. ** SIDE EFFECT: ** NOTE: the _sumk array is used to store all ** summation terms to avoid overflow. ** the predefined MAXTERM=512 allows the ** maximum angular momentum of about 500. ** if this limit is exceeded, the routine ** issues a warning. */ double W3j(int j1, int j2, int j3, int m1, int m2, int m3) { int i, k, kmin, kmax, ik[14]; double delta, qsum, a, b; #ifdef PERFORM_STATISTICS clock_t start, stop; start = clock(); #endif if (m1 + m2 + m3) return 0.0; if (!Triangle(j1, j2, j3)) return 0.0; if (abs(m1) > j1) return 0.0; if (abs(m2) > j2) return 0.0; if (abs(m3) > j3) return 0.0; ik[0] = j1 + j2 - j3; ik[1] = j1 - j2 + j3; ik[2] = -j1 + j2 + j3; ik[3] = j1 + j2 + j3 + 2; ik[4] = j1 - m1; ik[5] = j1 + m1; ik[6] = j2 - m2; ik[7] = j2 + m2; ik[8] = j3 - m3; ik[9] = j3 + m3; ik[10] = j2 - j3 - m1; ik[11] = j1 - j3 + m2; ik[12] = j3 - j2 + m1; ik[13] = j1 - j2 - m3; for (i = 0; i < 14; i++) { ik[i] = ik[i] / 2; } delta = - LnFactorial(ik[3]); for (i = 0; i < 3; i++) delta += LnFactorial(ik[i]); for (i = 4; i < 10; i++) delta += LnFactorial(ik[i]); kmin = Max(0, ik[10]); kmin = Max(kmin, ik[11]); kmax = Min(ik[0], ik[4]); kmax = Min(kmax, ik[7]); qsum = 0.0; a = 1E30; for (k = kmin, i = 0; k <= kmax && i < MAXTERM; k++, i++) { _sumk[i] = LnFactorial(k) + LnFactorial(ik[0]-k) + LnFactorial(ik[4]-k) + LnFactorial(ik[7]-k) + LnFactorial(ik[12]+k) + LnFactorial(k-ik[11]); if (_sumk[i] < a) a = _sumk[i]; } if (i == MAXTERM) { printf("Maximum terms in the 3j symbol sum reached\n"); printf("Results may be inaccurate\n"); } for (k = kmin, i = 0; k <= kmax; k++, i++) { b = exp(-(_sumk[i]-a)); if (IsOdd(k)) b = -b; qsum += b; } if (IsOdd(ik[13])) qsum = -qsum; b = exp(0.5*delta-a); b *= qsum; #ifdef PERFORM_STATISTICS stop = clock(); timing.w3j += stop -start; #endif return b; }