| Paste number 50135: | c++ kode |
| Pasted by: | olehsa |
| When: | 2 years, 4 months ago |
| Share: | Tweet this! | http://paste.lisp.org/+12ON |
| Channel: | None |
| Paste contents: |
// Variational Monte Carlo for atoms with up to two electrons
#include <cmath>
#include <iostream>
#include <fstream>
#include <iomanip>
#include "lib.h"
using namespace std;
// output file as global variable
ofstream ofile;
// the step length and its squared inverse for the second derivative
#define h 0.001
#define h2 1000000
// declaraton of functions
// Function to read in data from screen, note call by reference
void initialise(int&, int&, int&, int&, int&, int&, double&) ;
// The Mc sampling for the variational Monte Carlo
void mc_sampling(int, int, int, int, int, int, double, double *, double *);
// The variational wave function
double wave_function(double **, double, int, int);
// The local energy
double local_energy(double **, double, double, int, int, int);
// prints to screen the results of the calculations
void output(int, int, int, double *, double *);
// Begin of main program
//int main()
int main(int argc, char* argv[])
{
char *outfilename;
int number_cycles, max_variations, thermalization, charge;
int dimension, number_particles, numprocs, my_rank;
double step_length;
double *cumulative_e, *cumulative_e2;
// Read in output file, abort if there are too few command-line arguments
if( argc <= 1 ){
cout << "Bad Usage: " << argv[0] <<
" read also output file on same line" << endl;
exit(1);
}
else{
outfilename=argv[1];
}
ofile.open(outfilename);
// Read in data
initialise(dimension, number_particles, charge,
max_variations, number_cycles,
thermalization, step_length) ;
cumulative_e = new double[max_variations+1];
cumulative_e2 = new double[max_variations+1];
// Do the mc sampling
mc_sampling(dimension, number_particles, charge,
max_variations, thermalization,
number_cycles, step_length, cumulative_e, cumulative_e2);
// Print out results
output(max_variations, number_cycles, charge, cumulative_e, cumulative_e2);
delete [] cumulative_e; delete [] cumulative_e2;
ofile.close(); // close output file
return 0;
}
// Monte Carlo sampling with the Metropolis algorithm
void mc_sampling(int dimension, int number_particles, int charge,
int max_variations,
int thermalization, int number_cycles, double step_length,
double *cumulative_e, double *cumulative_e2)
{
int cycles, variate, accept, dim, i, j;
long idum;
double wfnew, wfold, alpha, energy, energy2, delta_e;
double **r_old, **r_new;
alpha = 0.5*charge;
idum=-1;
// allocate matrices which contain the position of the particles
r_old = (double **) matrix( number_particles, dimension, sizeof(double));
r_new = (double **) matrix( number_particles, dimension, sizeof(double));
for (i = 0; i < number_particles; i++) {
for ( j=0; j < dimension; j++) {
r_old[i][j] = r_new[i][j] = 0;
}
}
// loop over variational parameters
for (variate=1; variate <= max_variations; variate++){
// initialisations of variational parameters and energies
alpha += 0.1;
energy = energy2 = 0; accept =0; delta_e=0;
// initial trial position, note calling with alpha
// and in three dimensions
for (i = 0; i < number_particles; i++) {
for ( j=0; j < dimension; j++) {
r_old[i][j] = step_length*(ran1(&idum)-0.5);
}
}
wfold = wave_function(r_old, alpha, dimension, number_particles);
// loop over monte carlo cycles
for (cycles = 1; cycles <= number_cycles+thermalization; cycles++){
// new position
for (i = 0; i < number_particles; i++) {
for ( j=0; j < dimension; j++) {
r_new[i][j] = r_old[i][j]+step_length*(ran1(&idum)-0.5);
}
}
wfnew = wave_function(r_new, alpha, dimension, number_particles);
// Metropolis test
if(ran1(&idum) <= wfnew*wfnew/wfold/wfold ) {
for (i = 0; i < number_particles; i++) {
for ( j=0; j < dimension; j++) {
r_old[i][j]=r_new[i][j];
}
}
wfold = wfnew;
accept = accept+1;
}
// compute local energy
if ( cycles > thermalization ) {
delta_e = local_energy(r_old, alpha, wfold, dimension,
number_particles, charge);
// update energies
energy += delta_e;
energy2 += delta_e*delta_e;
}
} // end of loop over MC trials
cout << "variational parameter= " << alpha
<< " accepted steps= " << accept << endl;
// update the energy average and its squared
cumulative_e[variate] = energy/number_cycles;
cumulative_e2[variate] = energy2/number_cycles;
} // end of loop over variational steps
free_matrix((void **) r_old); // free memory
free_matrix((void **) r_new); // free memory
} // end mc_sampling function
// Function to compute the squared wave function, simplest form
double wave_function(double **r, double alpha,int dimension, int number_particles)
{
int i, j, k,l;
double wf, argument, r_single_particle, r_12;
double r_dum,r_tot, wave,r_beta,a , b;
b = alpha;
a = 1.7;
r_tot=0;
for(i=0; i<number_particles; i++){
r_dum=0;
for(j=0; j<number_particles; j++){
for(k=0; k<dimension; k++) {
for(l=0; l<dimension; l++) {
r_dum+=r[j][k]*r[i][l];
}
r_tot+=sqrt(r_dum);
}
}
}
r_12=0.;
r_dum=0.;
for(i=0; i<number_particles; i++){
r_dum=0;
for(j=0; j<number_particles; j++){
for(k=0; k<dimension; k++) {
for(l=0; l<dimension; l++) {
r_dum+=(r[j][k]-r[i][l])*(r[j][k]-r[i][l]);/* r_12 */
}
}
}
}
r_12+=r_dum;
r_12=sqrt(r_12);
r_beta=1./(1+b*r_12);
wave =exp(-a*r_tot+r_12*r_beta/2.);
return wave;
}
// Function to calculate the local energy with num derivative
double local_energy(double **r, double alpha, double wfold, int dimension,
int number_particles, int charge)
{
int i, j , k;
double e_local, wfminus, wfplus, e_kinetic, e_potential, r_12,
r_single_particle;
double **r_plus, **r_minus;
// allocate matrices which contain the position of the particles
// the function matrix is defined in the progam library
r_plus = (double **) matrix( number_particles, dimension, sizeof(double));
r_minus = (double **) matrix( number_particles, dimension, sizeof(double));
for (i = 0; i < number_particles; i++) {
for ( j=0; j < dimension; j++) {
r_plus[i][j] = r_minus[i][j] = r[i][j];
}
}
// compute the kinetic energy
e_kinetic = 0;
for (i = 0; i < number_particles; i++) {
for (j = 0; j < dimension; j++) {
r_plus[i][j] = r[i][j]+h;
r_minus[i][j] = r[i][j]-h;
wfminus = wave_function(r_minus, alpha, dimension, number_particles);
wfplus = wave_function(r_plus, alpha, dimension, number_particles);
e_kinetic -= (wfminus+wfplus-2*wfold);
r_plus[i][j] = r[i][j];
r_minus[i][j] = r[i][j];
}
}
// include electron mass and hbar squared and divide by wave function
e_kinetic = 0.5*h2*e_kinetic/wfold;
// compute the potential energy
e_potential = 0;
// contribution from electron-proton potential
for (i = 0; i < number_particles; i++) {
r_single_particle = 0;
for (j = 0; j < dimension; j++) {
r_single_particle += r[i][j]*r[i][j];
}
e_potential -= charge/sqrt(r_single_particle);
}
// contribution from electron-electron potential
for (i = 0; i < number_particles-1; i++) {
for (j = i+1; j < number_particles; j++) {
r_12 = 0;
for (k = 0; k < dimension; k++) {
r_12 += (r[i][k]-r[j][k])*(r[i][k]-r[j][k]);
}
e_potential += 1/sqrt(r_12);
}
}
free_matrix((void **) r_plus); // free memory
free_matrix((void **) r_minus);
e_local = e_potential+e_kinetic;
return e_local;
}
void initialise(int& dimension, int& number_particles, int& charge,
int& max_variations, int& number_cycles,
int& thermalization, double& step_length)
{
cout << "number of particles = ";
cin >> number_particles;
cout << "charge of nucleus = ";
cin >> charge;
cout << "dimensionality = ";
cin >> dimension;
cout << "maximum variational parameters = ";
cin >> max_variations;
cout << "# Thermalization steps= ";
cin >> thermalization;
cout << "# MC steps= ";
cin >> number_cycles;
cout << "# step length= ";
cin >> step_length;
} // end of function initialise
void output(int max_variations, int number_cycles, int charge,
double *cumulative_e, double *cumulative_e2)
{
int i;
double alpha, variance, error;
alpha = 0.5*charge;
for( i=1; i <= max_variations; i++){
alpha += 0.1;
variance = cumulative_e2[i]-cumulative_e[i]*cumulative_e[i];
error=sqrt(variance/number_cycles);
ofile << setiosflags(ios::showpoint | ios::uppercase);
ofile << setw(15) << setprecision(8) << alpha;
ofile << setw(15) << setprecision(8) << cumulative_e[i];
ofile << setw(15) << setprecision(8) << variance;
ofile << setw(15) << setprecision(8) << error << endl;
// fprintf(output_file, "%12.5E %12.5E %12.5E %12.5E \n", alpha,cumulative_e[i],variance, error );
}
// fclose (output_file);
} // end of function output
This paste has no annotations.