bool System::newStepMetropolis() { int i, j; double wf_new, wf_old; // taking a new, random step for (i=0; i<NumberOfParticles; i++) { for (j=0; j<NumberOfDimensions; j++) { NewPosition(i,j) = OldPosition(i,j)+StepLength*(ran0(&RandomSeed)-0.5); } } // calculating new wave-function wf_new = Wavefunction->evaluateWavefunction(NewPosition); wf_old = Wavefunction->getOldWavefunction(); // metropolis test: if(ran0(&RandomSeed) <= (wf_new*wf_new)/(wf_old*wf_old)) // STEP ACCEPTED { OldPosition = NewPosition; Wavefunction->setOldWavefunction(wf_new); return true; } else // STEP REFUSED { return false; } }
void PDESolver::GaussRandomWalk(vec *x){ double l0, r, theta, bin, L; vec X; long idum; int N,n; ofstream myfile; X = *x; l0 = sqrt(2*dt); idum = -1; bin = 1./20; myfile.open("MC_normal_movie.txt"); for (int t=0;t<=Nt;t++){ N = X.n_rows; n = 0; // n will determine how many new particles to be added in x = 0 for (int i=0;i<N;i++){ r = sqrt(-log(1. - ran0(&idum))); // Getting a random number theta = 2*pi*ran0(&idum); L = l0 * r*cos(theta); // From normal distribution if (X(i) < bin) {n += 1;} // This particle will move away from bin 0. Need to add one more. X(i) += L; // Particle changes position following the normal distribution if (X(i) < bin && X(i) >= 0) {n -= 1;} // This particle has arrived at bin 0. Need to add one less } int i = 0; while (i<N){ if (X(i) > 1){X.shed_row(i); N-=1;} // Remove particle and reduce total particle # else if (X(i) < 0){X.shed_row(i); N-=1;} // Remove particle and reduce total particle # else {i++;} } for (int i=0;i<n;i++){ X.insert_rows(0,1); X(0) = 0; // Maintaining # of particles at x=0 } for (int elem=0; elem<X.n_rows; elem++){myfile << X(elem) << " ";}; myfile << endl; } *x = sort(X); }
void fill_random(double *a, int isize) { long *idum; long i, j; j = 38282; idum = &j; a[0] = (double)ran0(idum); for (i=0; i<(long)isize; i++) { a[i] = (double)(10000.0*ran0(idum)); } }
void PDESolver::RandomWalk(vec *x) { double l0, r; vec X; long idum; int N,n; ofstream myfile; X = *x; l0 = sqrt(2*dt); idum = -1; myfile.open("MC_uniform_movie.txt"); for (int t=0;t<=Nt;t++){ N = X.n_rows; n = 0; // n will determine how many new particles to be added in x = 0 for (int i=0;i<N;i++){ r = ran0(&idum); // Getting a random number if (X(i) < 1e-13) {n += 1;} // This particle will move away from x0. Need to add one more. if (r>0.5) {X(i) += l0;} // Move to the right else {X(i) -= l0;} // Move to the left if (abs(X(i)) < 1e-13) {n -= 1;} // This particle has arrived at x0. Need to add one less } int i = 0; while (i<N){ if (X(i) > 1){X.shed_row(i); N-=1;} // Remove particle and reduce total particle # else if (X(i) < 0){X.shed_row(i); N-=1;} // Remove particle and reduce total particle # else {i++;} } for (int i=0;i<n;i++){ X.insert_rows(0,1); X(0) = 0; // Maintaining # of particles at x=0 } for (int elem=0; elem<X.n_rows; elem++){myfile << X(elem) << " ";}; myfile << endl; } *x = sort(X); }
void random_sphere(cube &data_vector,double R_0,long &idum,int n_planets){ double u; double v; double w; double c =2*M_PI; double r; double theta; double phi; for(int i=0;i<n_planets;i++){ u = ran0(&idum); v = ran0(&idum); w = ran0(&idum); r= R_0*pow(u,1./3); theta= acos(1.-2.*v); phi= c*w; data_vector(i,0,0) = r*sin(theta)*cos(phi);; data_vector(i,1,0) = r*sin(theta)*sin(phi); data_vector(i,2,0) = r*cos(theta); } }
float gasdev(long *idum) { float ran0(long *idum); static int iset=0; static float gset; float fac,rsq,v1,v2; if (iset == 0) { do { v1=2.0*ran0(idum)-1.0; v2=2.0*ran0(idum)-1.0; rsq=v1*v1+v2*v2; } while (rsq >= 1.0 || rsq == 0.0); fac=sqrt(-2.0*log(rsq)/rsq); gset=v1*fac; iset=1; return v2*fac; } else { iset=0; return gset; } }
short e_ran_g(short *seed0) { static int iset = 0; static long gset; long rsq, ltemp1, ltemp2; short sv1, sv2, rsq_s; short shft_fctr, stemp1; short shft_fctr1; /* ======================================================================== */ long ltmp1, ltmp2; short ans = 0; short stmp2; /* ======================================================================== */ if (iset == 0) { sv1 = shl(sub(ran0(seed0), 16384), 1); sv2 = shl(sub(ran0(seed0), 16384), 1); /* rsq = sv1 * sv1 + sv2 * sv2; */ ltemp1 = L_mult(sv1, sv1); ltemp2 = L_mult(sv2, sv2); rsq = L_add(L_shr(ltemp1, 1), L_shr(ltemp2, 1)); if (rsq >= 1073741824 || rsq == 0){ /* If condition not met, don't iterate; use */ /* rough approximation. */ ans = shr(sv1,3); ans = add(ans, shr(sv2,3)); ans = add(ans, shr(sub(ran0(seed0), 16384),2)); return (ans); } /* * error in rsq doesn't seem to contribute to the final error in e_ran_g */ /* * rsq scale down by two: input to fnLog must be scaled up by 2. */ rsq = L_shl(rsq, 1); /* stemp1 = round(L_negate(fnLog(rsq))); */ ltmp1 = L_negate(fnLog(rsq)); /* * rsq must be greater than the log of lsq for the fractional * divide to work. therfore normalize rsq. */ shft_fctr = norm_l(rsq); rsq_s = round(L_shl(rsq, shft_fctr)); stmp2 = (divide_s(round(ltmp1), rsq_s)); /* * stemp2 must be normalized before taking its square root. * (increases precision). */ shft_fctr1 = norm_s(stmp2); ltmp2 = L_deposit_h(shl(stmp2, shft_fctr1)); stemp1 = sqroot(ltmp2); /* * shifting involved before taking the square root: * LEFT << shft_fctr. (LEFT because rsq is in the denominator * of ltemp2 quotion). * LEFT << 6. (multiply by 2 in original code and multiply by 32 * because output of fnLog scaled down by 32). * RIGHT >> shft_fctr1. (normalization taken before sqroot). */ shft_fctr = shft_fctr + 6 - shft_fctr1; /* * PROPERTY: sqrt(2^n) = 2^(n/2) * if shft_fctr is odd; multiply stemp1 by sqrt(2)/2 and * increment number of shifts by 1. Can now use shft_fctr / 2. */ if (shft_fctr & 0x0001) { stemp1 = mult(stemp1, 23170); shft_fctr++; } shft_fctr = shr(shft_fctr, 1); /* * normalize stemp1 for the following multiplication. * adjust shft_fctr accordingly. */ shft_fctr1 = norm_s(stemp1); stemp1 = shl(stemp1, shft_fctr1); shft_fctr = shft_fctr - shft_fctr1; gset = L_mult(sv1, stemp1); /* * final output is scaled down by 4, therefore shift up by * shft_fctr - 2. */ gset = L_shl(gset, shft_fctr - 2); iset = 1; return round(L_shl(L_mult(sv2, stemp1), shft_fctr - 2)); } else { iset = 0; return round(gset); } }
int main(int argc, char** argv) { double lambda = atof(argv[2]); int N = atoi(argv[1]); double crude_mc,variance; crude_mc=0; double g_sigma = 0; int num_cores = 0; #if 0 double start = clock(); #pragma omp parallel { double l_sum = 0; double r1,r2,theta1,theta2,phi1,phi2; double fx = 0; double sum_sigma = 0; long idum1,idum2,idum3,idum4,idum5,idum6; idum1 = time(0)-123; idum2 = time(0)-383;idum3 = time(0)-73;idum4 = time(0)-239; idum5 = time(0)-830;idum6 = time(0)-955; #pragma omp for for(int i=0;i<N;i++){ r1 = lambda*ran0(&idum1); r2 = lambda*ran0(&idum2); theta1 = PI*ran0(&idum3); theta2 = PI*ran0(&idum4); phi1 = 2*PI*ran0(&idum5); phi2 = 2*PI*ran0(&idum6); fx = r1*r1*r2*r2*f_sub(r1,r2,theta1,theta2,phi1,phi2)*exp(-4*(r1+r2)); l_sum += fx; sum_sigma += fx*fx; } #pragma omp critical {crude_mc += l_sum; g_sigma += sum_sigma;num_cores = omp_get_num_threads();} } double stop = clock(); double diff = timediff(start,stop)*0.25; /* double var = ((pow(PI,4)*lambda*lambda*4)/N)*(g_sigma-((pow(PI,4)*lambda*lambda*4)/N)*crude_mc*crude_mc); cout<<"test: "<<var<<" sdv: "<<sqrt(var)<<" comparisson: "<<var/sqrt(N)<<endl;*/ crude_mc /= ((double) N); g_sigma /= ((double) N); variance = g_sigma - crude_mc*crude_mc; crude_mc *= lambda*lambda*4*pow(PI,4); cout<<"Monte Carlo simulation with N = "<<N<<" gives "<<crude_mc<<endl; cout<<"The variance is "<<variance<<" and standard deviation "<<sqrt(variance)<<endl; cout<<"This took "<<diff<<" ms on "<<num_cores<<" cores"<<endl; #else double start = clock(); #pragma omp parallel { /*Set up private variables for the paralell execution of this loop*/ double l_sum = 0; double l_sum2 = 0; double r1,r2,theta1,theta2,phi1,phi2; double fx = 0; double sum_sigma = 0; double sum_sigma2 = 0; long idum1,idum2,idum3,idum4,idum5,idum6; idum1 = time(0)-123; idum2 = time(0)-383;idum3 = time(0)-73;idum4 = time(0)-239; idum5 = time(0)-830;idum6 = time(0)-955; #pragma omp for for(int i=0;i<N;i++){ r1 = -log(1-ran0(&idum1)); r2 = -log(1-ran0(&idum2)); theta1 = PI*ran0(&idum3); theta2 = PI*ran0(&idum4); phi1 = 2*PI*ran0(&idum5); phi2 = 2*PI*ran0(&idum6); fx = (1./1024)*r1*r1*r2*r2*f_sub(r1,r2,theta1,theta2,phi1,phi2); if (l_sum > 1e4){ l_sum2 +=fx; sum_sigma2 +=fx*fx; } else{ l_sum += fx; sum_sigma += fx*fx; } } #pragma omp critical { crude_mc +=l_sum+l_sum2; g_sigma += sum_sigma+sum_sigma2; num_cores = omp_get_num_threads(); } } double stop = clock(); double diff = timediff(start,stop)*0.25; crude_mc /= ((double) N); g_sigma /= ((double) N); variance = g_sigma - crude_mc*crude_mc; crude_mc *= 4*pow(PI,4); cout<<"Monte Carlo simulation with (importance sampling) N = "<<N<<" gives "<<crude_mc<<endl; cout<<"correct result: "<<5*PI*PI/(16*16)<<endl; cout<<"The variance is "<<variance<<" and standard deviation "<<pow(4,PI)*sqrt(variance/((double) N))<<endl; cout<<"This took "<<diff<<" ms on "<<num_cores<<" cores"<<endl; #endif return 0; }
void System::initializePositionsBruteForce() { OldPosition = Mat<double>( NumberOfParticles, NumberOfDimensions ); NewPosition = Mat<double>( NumberOfParticles, NumberOfDimensions ); a_matrix = Mat<double>( NumberOfParticles, NumberOfParticles ); mat n = zeros(NumberOfParticles, NumberOfDimensions); //setting a random initial position: int i, j; for (i=0; i<NumberOfParticles; i++) { for (j=0; j<NumberOfDimensions; j++) { OldPosition(i,j) = StepLength*(ran0(&RandomSeed)-0.5); } } double N2 = float(NumberOfParticles)/2; // used for setting the a-variable in the jastrow factor // SETTING THE a-factor: for (i=0; i<NumberOfParticles-1; i++) { for (j=i+1; j<NumberOfParticles; j++) { // if-test for PARALLELL SPIN ( 0,1,2 = spin up | 3,4,5 = spin down): // N2 == 1 -> TWO PARTICLES -> PARALLELL SPIN: a = 1.0 if ( (N2 == 1 ) || (i < N2 && j < N2) || (i >= N2 && j >= N2) ) { a_matrix(i,j) = 1.0; } else // ANTI-PARALLELL SPIN { a_matrix(i,j) = 1.0/3.0; } } } // CREATING ENERGY STATE MATRIX (FOR 6 ELECTRONS) // FOR 2 ELECTRONS THIS WILL BE ZERO: if (NumberOfParticles == 6) { for (i=0; i<NumberOfParticles; i++) { if (i == 0 || i == 3) { n(i,0) = n(i,1) = 0; // nx = ny = 0 } if (i == 1 || i == 4) { n(i,0) = 1; // nx = 1 } if (i == 2 || i == 5) { n(i,1) = 1; // ny = 1 } } } // THIS MEANS THAT a(i,j) is the relative spin orientation between particle i+1 and j.+1 // so: a(0,1) = a12 . a(0,2) = a13 . a(1,2) = a23 . etc... Wavefunction->setA(a_matrix); Wavefunction->setN(n); Wavefunction->setOldWavefunction(Wavefunction->evaluateWavefunction(OldPosition)); }
void System::importanceSampling() { int NOA; // Number Of Accepted steps double I, I2, dx; // total energy integral double T, T2, dt; // kinetic energy integral double V, V2, dv; // potential energy integral int a,b,c,i,j; // loop variables: a->alpha, b->beta, c->cycles, i->particle, j-> dimension int amax = Alpha.n_elem; // number of total alpha values int bmax = Beta.n_elem; // number of total beta values double wf_new, wf_old; double greensfunction; double D = 0.5; // diffusion constant for (a=0; a<amax; a++) // LOOP OVER ALPHA VALUES { Wavefunction->setAlpha(a); TypeHamiltonian->getWavefunction()->setAlpha(a); for (b=0; b<bmax; b++) // LOOP OVER BETA VALUES { Wavefunction->setBeta(b); TypeHamiltonian->getWavefunction()->setBeta(b); dx = I = I2 = NOA = 0; dt = T = T2 = 0; dv = V = V2 = 0; // IMPORTANCE SAMPLING: for (c=0; c<NumberOfCycles; c++) { dx = 0; for (i=0; i<NumberOfParticles; i++) { // Taking a new, random step, moving one particle only: NewPosition = OldPosition; NewPosition.row(i) = OldPosition.row(i)+Rnd->nextGauss(0,sqrt(StepLength))+QuantumForceOld.row(i)*StepLength*D; wf_new = Wavefunction->evaluateWavefunction(NewPosition); quantumForce(NewPosition,QuantumForceNew,wf_new); // Metropolis-Hastings algorithm: greensfunction = 0.0; for(j=0;j<NumberOfDimensions;j++) { greensfunction += 0.5*(QuantumForceOld(i,j) + QuantumForceNew(i,j))*(D*StepLength*0.5*(QuantumForceOld(i,j)-QuantumForceNew(i,j)) - NewPosition(i,j) + OldPosition(i,j)); } greensfunction = exp(greensfunction); // Metropolis test: if (ran0(&RandomSeed) <= greensfunction*wf_new*wf_new/(wf_old*wf_old)) { OldPosition.row(i) = NewPosition.row(i); QuantumForceOld.row(i) = QuantumForceNew.row(i); Wavefunction->setOldWavefunction(wf_new); wf_old = wf_new; } } // Updating integral: // LOCAL ENERGY dx = TypeHamiltonian->evaluateLocalEnergy(OldPosition); I += dx; I2 += dx*dx; // LOCAL KINETIC ENERGY dt = TypeHamiltonian->getKineticEnergy(); T += dt; T2 += dt*dt; // LOCAL POTENTIAL ENERGY dv = TypeHamiltonian->getPotentialEnergy(); V += dv; V2 += dv*dv; NOA++; } NumberOfAcceptedSteps(a,b) = NOA; Energy(a,b) = I/double(NumberOfCycles); EnergySquared(a,b) = I2/double(NumberOfCycles); Variance(a,b) = (EnergySquared(a,b) - Energy(a,b)*Energy(a,b)); KineticEnergy(a,b) = T/double(NumberOfCycles); KineticEnergySquared(a,b) = T2/double(NumberOfCycles); PotentialEnergy(a,b) = V/double(NumberOfCycles); PotentialEnergySquared(a,b) = V2/double(NumberOfCycles); //AvgDistance = 0; } } }