/** * Constructor * @param Trial - pointer to trial wavefunction * @param H - Hamiltonian of the system * @param seed - seed for normal random number generator * @param idum - seed for uniform random number generator */ Metropolis_Hastings::Metropolis_Hastings(Wavefunction* Trial, Hamiltonian* H, long idum) { this->Trial = Trial; this->dim = Trial->get_dim(); this->numpart = Trial->get_numpart(); this->H = H; this->idum = idum; QFo = new QForce(Trial); R_cur.set_size(numpart, dim); R_tr.set_size(numpart, dim); delta = 0.5; interaction = Trial->get_int(); seed = (int) abs(idum); RanNormalSetSeedZigVec(&seed, 200); // Initialize random number generator exp_par_psi = zeros(2); exp_par_psi2 = zeros(2); par_psi = zeros(2); }
/******************************************************************* * * NAME : run_importance_sampling(int cycles, int& accepted, * double& energy, double& energy_sq) * * DESCRIPTION : Importance sampling */ void MC_Importance_Sampling::run_importance_sampling(int cycles, int& accepted, double& energy, double& energy_sq) { int dum = (int) idum; RanNormalSetSeedZigVec(&dum, 200); // Special case for blocking. We need the rank when writing to file. #if BLOCKING int my_rank; MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); ostringstream filename; filename << "Blocking/files/blocking_" << my_rank << ".dat"; ofstream blockfile(filename.str().c_str(), ios::out | ios::binary); #endif double delta_e, greens_function, R; int n_particles = wf->getNParticles(); int dim = wf->getDim(); // Initiating variables energy = 0; energy_sq = 0; accepted = 0; delta_e = 0; // Quantum Force. mat q_force_old = zeros(n_particles, dim); mat q_force_new = zeros(n_particles, dim); // Initial position of the electrons mat r_old = randn(n_particles, dim) * sqrt(dt); mat r_new = r_old; // Evalutating the Quantum Force and Wave Function in the inital position. wf->set_r_new(r_old, 0); wf->init_slater(); q_force_old = wf->q_force(); wf->accept_move(); // Monte Carlo cycles for (int sample = 0; sample < (cycles + thermalization); sample++) { // Looping over all particles. for (int active = 0; active < n_particles; active++) { // Using the quantum force to calculate a new position. for (int i = 0; i < dim; i++) r_new(active, i) = r_old(active, i) + D * q_force_old(active, i) * dt + DRanNormalZigVec() * sqrt(dt); // Evaluating the Wave Function in r_new. wf->set_r_new(r_new, active); wf->evaluate_new(); // Updating the quantum force. q_force_new = wf->q_force(); // Calculating the ratio between the Green's functions. greens_function = 0; for (int j = 0; j < dim; j++) { greens_function += (q_force_old(active, j) + q_force_new(active, j)) * (D * dt * 0.5 * (q_force_old(active, j) - q_force_new(active, j)) - r_new(active, j) + r_old(active, j)); } greens_function = exp(0.5 * greens_function); // Metropolis-Hastings acceptance test. R = wf->get_ratio(); R = R * R *greens_function; if (ran3(&idum) <= R) { r_old = r_new; q_force_old = q_force_new; wf->accept_move(); if (sample > thermalization) { accepted++; delta_e = ht->get_energy(r_old); } } else { // If the move is not accepted the position and quantum force is reset. r_new = r_old; q_force_new = q_force_old; } // Sampling the energy. if (sample > thermalization) { energy += delta_e; energy_sq += delta_e*delta_e; #if BLOCKING blockfile.write((char*) &delta_e, sizeof (double)); #endif } } } // End MC cycles. // Scaling the results. energy = energy / cycles / n_particles; energy_sq = energy_sq / cycles / n_particles; accepted /= n_particles; #if BLOCKING blockfile.close(); #endif }