void Compute_Forces(gsl_matrix * Positions, gsl_matrix * Velocities, gsl_matrix * Neighbors, gsl_vector * ListHead, gsl_vector * List, int type1, int type2, gsl_matrix * Forces, gsl_vector * Energy, gsl_vector * Kinetic ) { // RESET MATRICES AND VECTORS // TODO: Redundant? gsl_matrix_set_zero(Forces); gsl_vector_set_zero(Energy); gsl_vector_set_zero(Kinetic); // Begin of parallel region int omp_get_max_threads(); int chunks = NParticles / omp_get_max_threads(); #pragma omp parallel { #pragma omp for schedule (dynamic,chunks) for (int i=0;i<NParticles;i++) { gsl_vector_view vi = gsl_matrix_row(Velocities, i); double * fij = malloc(3*sizeof(double)); // Compute the kinetic energy of particle i (0.5 mi vi^2) double ei = KineticEnergy(&vi.vector, (int) gsl_matrix_get(Positions,i,0)); gsl_vector_set(Kinetic,i,ei); // Obtain the list of neighboring cells to iCell (the cell i belongs to) int iCell = FindParticle(Positions,i); gsl_vector_view NeighboringCells = gsl_matrix_row(Neighbors, iCell); // Obtain the list of neighboring particles that interacts with i // i interacts with all Verlet[j] particles (j = 0 .. NNeighbors-1) int * Verlet = malloc(27 * NParticles * sizeof(int) / (Mx*My*Mz)); int NNeighbors = Compute_VerletList(Positions, i, &NeighboringCells.vector, iCell, ListHead, List, Verlet); // Loop over all the j-neighbors of i-particle for (int j=0;j<NNeighbors;j++) { ei = Compute_Force_ij(Positions, i, Verlet[j], type1, type2, fij); Forces->data[i*Forces->tda + 0] += fij[0]; Forces->data[i*Forces->tda + 1] += fij[1]; Forces->data[i*Forces->tda + 2] += fij[2]; Energy->data[i*Energy->stride] += ei; } free(Verlet); free(fij); } } // End of parallel region }
/***=======================================================================***/ void NHThermostat(cellgrid *CG, coord *crd, prmtop *tp, trajcon *tj, Energy *sysUV, double ETAt, double *CHIt, double *CHItp1e, double *CHItp1q, int barostat) { int i, j, g3con; double dt, Ttarget, pmass, qmass, invqmass, sigma, vfac; double *vtmp; cell *C; /*** Unpack ***/ dt = (barostat == 1) ? 0.125*sqrt(418.4)*tj->dt : 0.25*sqrt(418.4)*tj->dt; Ttarget = (barostat == 1) ? GASCNST*tj->Ttarget : 0.0; pmass = (barostat == 1) ? ETAt*ETAt*tj->npth.pmass : 0.0; qmass = tj->npth.qmass; sigma = 2.0*tj->npth.sigma; invqmass = 1.0/qmass; /*** Compute the kinetic energy ***/ sysUV->kine = KineticEnergy(CG, crd, tp, tj); *CHItp1e = *CHIt + dt*(2.0*sysUV->kine + pmass - sigma - Ttarget)*invqmass; const int ncell = CG->ng[0]*CG->ng[1]*CG->ng[2]; vtmp = crd->vel; vfac = exp(-2.0*dt*(*CHItp1e)); for (i = 0; i < ncell; i++) { C = &CG->data[i]; for (j = 0; j < C->nr[0]; j++) { g3con = 3*C->data[j].id; vtmp[g3con] *= vfac; vtmp[g3con+1] *= vfac; vtmp[g3con+2] *= vfac; } } sysUV->kine = KineticEnergy(CG, crd, tp, tj); *CHItp1q = *CHItp1e + dt*(2.0*sysUV->kine + pmass - sigma - Ttarget)*invqmass; }
double MeanKineticEnergy ( const MDConstants K, const Molecule **positions, const TurbField **turb_velocities ) { double time_mean = 0; for (unsigned n = 0; n < K.SnapshotNum; ++n) // calc mean over time { double part_mean = 0; //for every new timestep for (unsigned i = 0; i < K.PartNum; ++i)//calc mean over particles { double v_part[kDIM] = {0}; double v_0[kDIM]; InitConstArray (v_0, kDIM, K.v_0);// v_0 * \vec{e_part} NormalizeVector (v_0, positions[n][i].direction, v_part); double v[kDIM]; //temp array SumVector (v_part, turb_velocities[n][i].direction, v); double kin_energy = KineticEnergy (v); part_mean += kin_energy; assert (part_mean >= 0); } part_mean /= K.PartNum; time_mean += part_mean; assert (time_mean > 0); } time_mean /= (K.iteration_num * K.delta_t); return time_mean; }
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; } } }
void System::runMonteCarlo() { int i, j, k, NOA; int alpha_max = Alpha.n_elem; int beta_max = Beta.n_elem; double I, I2, dx; // total energy integral double T, T2, dt; // kinetic energy integral double V, V2, dv; // potential energy integral bool Accepted; for (i=0; i<alpha_max; i++) // LOOP OVER ALPHA VALUES { Wavefunction->setAlpha(i); TypeHamiltonian->getWavefunction()->setAlpha(i); for (j=0; j<beta_max; j++) // LOOP OVER BETA VALUES { Wavefunction->setBeta(j); TypeHamiltonian->getWavefunction()->setBeta(j); dx = I = I2 = NOA = 0; dt = T = T2 = 0; dv = V = V2 = 0; // BRUTE FORCE METROPOLIS: for (k=0; k<NumberOfCycles; k++) { Accepted = newStepMetropolis(); // NEW STEP: ACCEPTED OR REFUSED if (Accepted) { // 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++; } else { I += dx; I2 += dx*dx; T += dt; T2 += dt*dt; V += dv; V2 += dv*dv; } } NumberOfAcceptedSteps(i,j) = NOA; Energy(i,j) = I/double(NumberOfCycles); EnergySquared(i,j) = I2/double(NumberOfCycles); Variance(i,j) = (EnergySquared(i,j) - Energy(i,j)*Energy(i,j)); KineticEnergy(i,j) = T/double(NumberOfCycles); KineticEnergySquared(i,j) = T2/double(NumberOfCycles); PotentialEnergy(i,j) = V/double(NumberOfCycles); PotentialEnergySquared(i,j) = V2/double(NumberOfCycles); } } }