int main(int argc, char *argv[]) { if (argc < 9) { printf("Usage: %s <N> <eta> <dr> <nequil> <nproduct> <binwidth>\n", argv[0]); printf("\t<N> Number of particles\n"); printf("\t<rho> Particle density\n"); printf("\t<T> Temperature\n"); printf("\t<rc> Lennard-Jones cut-off radius\n"); printf("\t<dt> Length of one timestep\n"); printf("\t<nequil> Number of equilibration timesteps to be performed\n"); printf("\t<nproduct> Number of production timesteps to be performed\n"); printf("\t<binwidth> Width of a bin for correlation length histogram\n"); exit(EXIT_SUCCESS); } outGr = fopen("outGr.txt", "w+"); outTrajectories = fopen("outTrajectories.txt", "w+"); outAverages = fopen("outAverages.txt", "w+"); // Parse commandline parameters N = atoi(argv[1]); rho = atof(argv[2]); T = atof(argv[3]); rc = atof(argv[4]); rc2 = rc*rc; dt = atof(argv[5]); nequil = atof(argv[6]); nproduct = atof(argv[7]); nt = nequil+nproduct; double tequil = nequil*dt; double tproduct = nproduct*dt; tmax = nt*dt; // Calculate corresponding system parameters lx = ly = sqrt((double)N/rho); printf("========== PARAMETERS ==========\n"); printf("Particles:\t\t%d\n", N); printf("Density:\t\t%g\n", rho); printf("Simulationbox lx:\t%g\n", lx); printf("Simulationbox ly:\t%g\n", ly); printf("Temperature:\t\t%g\n", T); printf("Timestep length:\t%g\n", dt); printf("Equilibration steps:\t%d\n", nequil); printf("Production steps:\t%d\n", nproduct); printf("Total steps:\t%d\n", nt); printf("Equilibration time:\t%g\n", tequil); printf("Production time:\t%g\n", tproduct); printf("Total time:\t\t%g\n", tmax); printf("================================\n\n"); printf("======== INIT PARTICLES ========\n"); // Initialize arrays for particle positions & velocities r = new TVector[N]; r_next = new TVector[N]; v = new TVector[N]; v_next = new TVector[N]; // Put all particles equally spaced in the box and assign random velocities int nrows = sqrt(N); double dlx = lx/(double)nrows; double dly = ly/(double)nrows; vsum = .0; vsum2 = 0; for (int i = 0; i < N; i++) { // Positions r[i].x = i%nrows*dlx+0.5; r[i].y = floor(i/nrows)*dly+0.5; // Velocities v[i].x = rand_value(-1., 1.); v[i].y = rand_value(-1., 1.); vsum += v[i]; vsum2 += v[i].x*v[i].x + v[i].y*v[i].y; } printf("Center of mass velocity after initialization:\t(%g,%g)\n", vsum.x, vsum.y); printf("Kinetic energy after initialization:\t\t%g\n", vsum2); printf("Instantaneous temperature after initialization:\t%g\n", vsum2/(2.0*(double)N)); // Calculate average velocities vsum = vsum/(double)N; // Scalefactor for velocities to match the desired temperature (we neglect the fact // that the whole system with constrained center of mass has only (2N - 2) degrees // of freedom and approximate (2N - 2) \approx 2N since we won't run the simulation // with less than N = 100 particles.) double fs = sqrt(2.0*(double)N*T/vsum2); printf("Scaling factor for velocities:\t\t\t%g\n", fs); TVector vsumcheck; vsumcheck = .0; vsum2 = 0; for (int i = 0; i < N; i++) { v[i] = (v[i]-vsum)*fs; vsumcheck += v[i]; vsum2 += v[i].x*v[i].x + v[i].y*v[i].y; } printf("Center of mass velocity after scaling:\t\t(%g,%g)\n", vsumcheck.x, vsumcheck.y); printf("Kinetic energy after scaling:\t\t\t%g\n", vsum2); printf("Instantaneous temperature after scaling:\t%g\n", vsum2/(2.0*(double)N)); print_coords("outCoords_start.txt"); printf("================================\n\n"); printf("======== INIT POTENTIAL ========\n"); // Init the potential init_lj_shift(); F = new TVector[N]; printf("Potential initialized.\n"); printf("U(r_c)\t\t= %g\n", u_lj_shift); printf("U'(r_c)\t\t= %g\n", u_lj_deriv_shift); printf("U_s(r_c)\t= %g\n", u_lj_shifted(rc2)); printf("U'_s(r_c)\t= %g\n", u_lj_deriv_shifted(rc2)); printf("================================\n\n"); printf("======== INIT AVERAGERS ========\n"); avg_temp.init(); avg_epot.init(); avg_ekin.init(); avg_etot.init(); avg_vir.init(); printf("Averagers initialized!\n"); // Histogram for pair correlation function binwidth = atof(argv[8]); // Width of a histogram-bin nbins = ceil(grmax/binwidth); // Maximum correlation length to be measured should be L/2 due to periodic BC bincount = 0; // Number of counts done on the histogram hist = new int[nbins]; for (int i = 0; i < nbins; i++) { hist[i] = 0; } printf("Using histogram with %d bins of width %f\n", nbins, binwidth); printf("================================\n\n"); printf("======= START INTEGRATION ======\n"); t = 0; fprintf(outTrajectories, "#t\tn\tr_x\t\tr_y\t\tv_x\t\tv_y\n"); fprintf(outAverages, "#t\tT(t)\t\t<T(t)>\t\tE_tot(T)\t\t<E_tot(T)>\n"); for (int n = 0; n <= nt; n++) { if (n == 0) { printf("Equilibration phase started.\n"); } if (n == nequil) { printf("Production phase started.\n"); } // Current time t = dt*n; if(debug) printf("t:\t%6.3f\t\n", t); // Calculate all forces forces(); vsum = .0; vsum2 = .0; // update all particles for (int i = 0; i < N; i++) { // perform leap-frog-integration v_next[i] = v[i] + F[i]*dt; r_next[i] = r[i] + v_next[i]*dt; // Calculate energies vsum += v_next[i]; // vsum2 += v[i].x*v[i].x + v[i].y*v[i].y; // naiv? vsum2 += pow(v_next[i].x+v[i].x, 2)/4.0 + pow(v_next[i].y+v[i].y, 2)/4.0; // sophisticated by Frenkel/Smit // update particle coordinates v[i] = v_next[i]; r[i] = r_next[i]; // Write trajectories to a file // fprintf(outTrajectories, "%6.3f\t%6d\t%e\t%e\t%e\t%e\n", t, i, r[i].x, r[i].y, v[i].x, v[i].y); } // Equilibration phase, scale velocities to keep temperature if (n < nequil) { // Rescale velocities every ?? timesteps if (n%10 == 0) { scale_velocities(); } } else if (n%nsamp == 0) { double Tt = vsum2/(2.0*(double)N); avg_temp.add(Tt); avg_epot.add(epot); avg_vir.add(virial); double ekin = 0.5*vsum2; avg_ekin.add(ekin); double etot = (epot + ekin); avg_etot.add(etot); update_histogram(); fprintf(outAverages, "%6.3f\t%e\t%e\t%e\t%e\n", t, Tt, avg_temp.average(), etot, avg_etot.average()); } if ((n+1)%(nt/10) == 0 || n == 0) { printf("Finished %5d (t = %5.1f) out of %d (t = %g) timesteps: %3.f %% <T> = %g\n", n+1, t, nt, tmax, (double)n/(double)nt*100, avg_temp.average()); } if(debug) printf("\n"); } printf("================================\n\n"); print_coords("outCoords_end.txt"); printf("Printing histogram for g(r) & calculating pressure\n"); fprintf(outGr, "#r\tg(r)\n"); double p = 0; // Pressure for(int i = 0; i < nbins; i++) { double R = i*binwidth; double area = 2.0*PI*R*binwidth; // Multiply g(r) by two, since in the histogram we only counted each pair once, but each pair // gives two contributions to g(r) double gr = 2.0*(double)hist[i]/(rho*area*(double)bincount*N); fprintf(outGr, "%f\t%f\n", R, gr); // Calculate other quantities from g(r) if (R > 0 && R < rc) { double r6i = pow(1.0/R, 6); p += gr*2*PI*rho*rho*R*R*48*(r6i*r6i-0.5*r6i)*binwidth/2; } } p = p + rho*avg_temp.average(); printf("Final pressure P(%g) = %g\n", rho, p); FILE *outAvgFinal; outAvgFinal = fopen("outAvgFinal.txt", "w+"); fprintf(outAvgFinal, "#t\t<T(t)>\t\t<E_tot(T)>\trho\t\t1/rho\t\tp\n"); fprintf(outAvgFinal, "%6.3f\t%e\t%e\t%e\t%e\t%e\n", t, avg_temp.average(), avg_etot.average(), rho, 1.0/rho, p); fclose(outAvgFinal); outAvgFinal = NULL; delete [] r; delete [] r_next; delete [] v; delete [] v_next; delete [] F; r = r_next = v = v_next = F = NULL; // Close filepointer fclose(outGr); outGr = NULL; fclose(outTrajectories); outTrajectories = NULL; fclose(outAverages); outAverages = NULL; exit(EXIT_SUCCESS); }
gmx_bool replica_exchange(FILE *fplog, const t_commrec *cr, struct gmx_repl_ex *re, t_state *state, gmx_enerdata_t *enerd, t_state *state_local, gmx_int64_t step, real time) { int i, j; int replica_id = 0; int exchange_partner; int maxswap = 0; /* Number of rounds of exchanges needed to deal with any multiple * exchanges. */ /* Where each replica ends up after the exchange attempt(s). */ /* The order in which multiple exchanges will occur. */ gmx_bool bThisReplicaExchanged = FALSE; if (MASTER(cr)) { replica_id = re->repl; test_for_replica_exchange(fplog, cr->ms, re, enerd, det(state_local->box), step, time); prepare_to_do_exchange(fplog, re->destinations, replica_id, re->nrepl, &maxswap, re->order, re->cyclic, re->incycle, &bThisReplicaExchanged); } /* Do intra-simulation broadcast so all processors belonging to * each simulation know whether they need to participate in * collecting the state. Otherwise, they might as well get on with * the next thing to do. */ if (DOMAINDECOMP(cr)) { #ifdef GMX_MPI MPI_Bcast(&bThisReplicaExchanged, sizeof(gmx_bool), MPI_BYTE, MASTERRANK(cr), cr->mpi_comm_mygroup); #endif } if (bThisReplicaExchanged) { /* Exchange the states */ /* Collect the global state on the master node */ if (DOMAINDECOMP(cr)) { dd_collect_state(cr->dd, state_local, state); } else { copy_state_nonatomdata(state_local, state); } if (MASTER(cr)) { /* There will be only one swap cycle with standard replica * exchange, but there may be multiple swap cycles if we * allow multiple swaps. */ for (j = 0; j < maxswap; j++) { exchange_partner = re->order[replica_id][j]; if (exchange_partner != replica_id) { /* Exchange the global states between the master nodes */ if (debug) { fprintf(debug, "Exchanging %d with %d\n", replica_id, exchange_partner); } exchange_state(cr->ms, exchange_partner, state); } } /* For temperature-type replica exchange, we need to scale * the velocities. */ if (re->type == ereTEMP || re->type == ereTL) { scale_velocities(state, sqrt(re->q[ereTEMP][replica_id]/re->q[ereTEMP][re->destinations[replica_id]])); } } /* With domain decomposition the global state is distributed later */ if (!DOMAINDECOMP(cr)) { /* Copy the global state to the local state data structure */ copy_state_nonatomdata(state, state_local); } } return bThisReplicaExchanged; }
gmx_bool replica_exchange(FILE *fplog,const t_commrec *cr,struct gmx_repl_ex *re, t_state *state,real *ener, t_state *state_local, int step,real time) { gmx_multisim_t *ms; int exchange=-1,shift; gmx_bool bExchanged=FALSE; ms = cr->ms; if (MASTER(cr)) { exchange = get_replica_exchange(fplog,ms,re,ener,det(state->box), step,time); bExchanged = (exchange >= 0); } if (PAR(cr)) { #ifdef GMX_MPI MPI_Bcast(&bExchanged,sizeof(gmx_bool),MPI_BYTE,MASTERRANK(cr), cr->mpi_comm_mygroup); #endif } if (bExchanged) { /* Exchange the states */ if (PAR(cr)) { /* Collect the global state on the master node */ if (DOMAINDECOMP(cr)) { dd_collect_state(cr->dd,state_local,state); } else { pd_collect_state(cr,state); } } if (MASTER(cr)) { /* Exchange the global states between the master nodes */ if (debug) { fprintf(debug,"Exchanging %d with %d\n",ms->sim,exchange); } exchange_state(ms,exchange,state); if (re->type == ereTEMP) { scale_velocities(state,sqrt(re->q[ms->sim]/re->q[exchange])); } } /* With domain decomposition the global state is distributed later */ if (!DOMAINDECOMP(cr)) { /* Copy the global state to the local state data structure */ copy_state_nonatomdata(state,state_local); if (PAR(cr)) { bcast_state(cr,state,FALSE); } } } return bExchanged; }