void BOCTX::Sweep(SEGM2 * aSegms, UINT32 nSegms) { CollectEvents(aSegms, nSegms); while (not m_E.empty()) { // store the current state of main active list SAVE_LIST save_list; save_list.reserve(32); for (SEGM_LIST::iterator segm = m_S.begin(); segm != m_S.end(); ++segm) save_list.push_back(&*segm); // do Pass 1 EVENT e = m_E.top(); m_E.pop(); EVENTLIST elist; elist.reserve(8); assert(INT20_MIN <= e.x and e.x <= INT20_MAX); AddEvent(&elist, e); HandleEvent(e); while (not m_E.empty() and m_E.top().x == e.x) { e = m_E.top(); m_E.pop(); AddEvent(&elist, e); HandleEvent(e); } // do Pass 2 Pass2(&elist, &save_list); } } // Sweep
int main() { unsigned int i, im, iw; const double pressure = 2.0; // pressure const double beta = 0.5; // inverse temperature const double mass[2] = { 1, 3 }; // alternating masses const unsigned int nsweeps = 13; // number of 'sweeps' of the event table // enable run-time memory check for debug builds #if defined(_WIN32) & (defined(DEBUG) | defined(_DEBUG)) _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif printf("pressure: %g\n", pressure); printf("beta: %g\n", beta); printf("alternating masses: (%g, %g)\n", mass[0], mass[1]); printf("N: %d\n", NUM_SITES); assert(NUM_SITES == 16); // artificial UNIX time unsigned int itime = 1420000241; // random generator seed; multiplicative constant from Pierre L'Ecuyer's paper randseed_t seed; Random_SeedInit(1865811235122147685LL * (uint64_t)itime, &seed); // lattice field field_t f; Field_Create(mass, &f); // initialize elongations and momenta using single-site probability density, Eq. (2.11) EquilibrateCanonical(pressure, beta, &seed, &f); // initial mean values double r_mean0 = 0; // mean of r's (elongations), remains constant in time double p_mean0 = 0; // mean momentum double e_mean0 = 0; // mean energy for (im = 0; im < 2; im++) { for (i = im; i < NUM_SITES; i += 2) { const lattpoint_t *point = &f.pts[i]; r_mean0 += point->r; // elongation p_mean0 += mass[im] * point->v; // momentum e_mean0 += LattPoint_Energy(mass[im], point); // energy } } r_mean0 /= NUM_SITES; p_mean0 /= NUM_SITES; e_mean0 /= NUM_SITES; //e_mean0 -= 0.5 * square(p_mean0); // internal energy per particle // stochastic expectation values double r_avr = AverageElongation(pressure, beta); double p_avr = 0; double e_avr = AverageEnergy(beta); // compare mean values with stochastic expectation values printf("elongation mean: %g, stochastic average: %g\n", r_mean0, r_avr); printf("momentum mean: %g, stochastic average: %g\n", p_mean0, p_avr); printf("energy mean: %g, stochastic average: %g\n", e_mean0, e_avr); // save elongations and momenta to disk { double r[NUM_SITES]; double p[NUM_SITES]; for (im = 0; im < 2; im++) { for (i = im; i < NUM_SITES; i += 2) { r[i] = f.pts[i].r; p[i] = mass[im] * f.pts[i].v; } } WriteData("../test/collision_test_field_r0.dat", r, sizeof(double), NUM_SITES, false); WriteData("../test/collision_test_field_p0.dat", p, sizeof(double), NUM_SITES, false); } // event table event_table_t tab; assert(NUM_SLOTS == 4); EventTable_Allocate(0.1, &tab); // dt, table printf("event table number of slots: %i, slot interval dt: %g, events per slot: %i\n", NUM_SLOTS, tab.dt, EVENTS_PER_SLOT); // time period const double period = NUM_SLOTS * tab.dt; printf("event table time period: %g\n", period); // initial kinetic and potential energy double en0 = Field_Energy(&f); printf("initial energy: %g\n", en0); // collect collision events CollectEvents(&f, &tab); for (iw = 0; iw < nsweeps; iw++) // several sweeps { // process events SweepTable(&f, &tab); // synchronize up to period of event table Field_Synchronize(period, &f); // subtract 'period' from all timing events GlobalTimeshift(period, &f, &tab); // correspondingly add 'period' to time offset of event log #ifdef _DEBUG event_log.time_offset += period; #endif } printf("finished simulation, simulation time: %g\n", nsweeps * period); // final mean values (should be conserved) double r_mean1 = 0; // mean of r's (elongations), remains constant in time double p_mean1 = 0; // mean momentum double e_mean1 = 0; // mean energy for (im = 0; im < 2; im++) { for (i = im; i < NUM_SITES; i += 2) { const lattpoint_t *point = &f.pts[i]; r_mean1 += point->r; // elongation p_mean1 += mass[im] * point->v; // momentum e_mean1 += LattPoint_Energy(mass[im], point); // energy } } r_mean1 /= NUM_SITES; p_mean1 /= NUM_SITES; e_mean1 /= NUM_SITES; //e_mean1 -= 0.5 * square(p_mean1); // internal energy per particle // compare initial and final mean values (should be conserved) printf("final elongation mean: %g, difference to initial value: %g (should be zero)\n", r_mean1, fabs(r_mean0 - r_mean1)); printf("final momentum mean: %g, difference to initial value: %g (should be zero)\n", p_mean1, fabs(p_mean0 - p_mean1)); printf("final energy mean: %g, difference to initial value: %g (should be zero)\n", e_mean1, fabs(e_mean0 - e_mean1)); // final energy double en1 = Field_Energy(&f); printf("final energy: %g\n", en1); printf("energy difference: %g (should be zero)\n", en1 - en0); #ifdef _DEBUG // report events i = 0; event_node_t *node = event_log.first; double *evtime = malloc(event_log.num * sizeof(double)); int *eviprt = malloc(event_log.num * sizeof(int)); int *evtype = malloc(event_log.num * sizeof(int)); while (node != NULL) { printf("next event: time: %g, iprt: %i, type: %s\n", node->ev.time, node->ev.iprt, COLL_STR[node->ev.type]); evtime[i] = node->ev.time; eviprt[i] = node->ev.iprt; evtype[i] = node->ev.type; node = node->next; i++; } assert(i == event_log.num); // save event data to disk WriteData("../test/collision_test_event_time.dat", evtime, sizeof(double), event_log.num, false); WriteData("../test/collision_test_event_iprt.dat", eviprt, sizeof(int), event_log.num, false); WriteData("../test/collision_test_event_type.dat", evtype, sizeof(int), event_log.num, false); // read reference data from disk double *evtime_ref = malloc(event_log.num * sizeof(double)); int *eviprt_ref = malloc(event_log.num * sizeof(int)); int *evtype_ref = malloc(event_log.num * sizeof(int)); ReadData("../test/collision_test_ref_event_time.dat", evtime_ref, sizeof(double), event_log.num); ReadData("../test/collision_test_ref_event_iprt.dat", eviprt_ref, sizeof(int), event_log.num); ReadData("../test/collision_test_ref_event_type.dat", evtype_ref, sizeof(int), event_log.num); // calculate average error printf("comparing with reference collision data...\n"); double err = 0; for (i = 0; i < event_log.num; i++) { err += fabs(evtime[i] - evtime_ref[i]); err += abs(eviprt[i] - eviprt_ref[i]); err += abs(evtype[i] - evtype_ref[i]); } err /= event_log.num; printf("average error: %g\n", err); // clean up free(evtype); free(eviprt); free(evtime); free(evtype_ref); free(eviprt_ref); free(evtime_ref); EventLog_Delete(&event_log); #endif // _DEBUG // clean up EventTable_Delete(&tab); return 0; }
int main() { unsigned int i, j; const double pressure = 1.2; // pressure const double beta = 2.0; // inverse temperature const unsigned int nsweeps = /*500*/250; // number of 'sweeps' of the event table // enable run-time memory check for debug builds #if defined(_WIN32) & (defined(DEBUG) | defined(_DEBUG)) _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif printf("pressure: %g\n", pressure); printf("beta: %g\n", beta); printf("N: %d\n", NUM_SITES); assert(NUM_SITES == 256); // lattice field field_t f; Field_Create(&f); { // artificial UNIX time unsigned int itime = 1420000241; // random generator seed; multiplicative constant from Pierre L'Ecuyer's paper randseed_t seed; Random_SeedInit(1865811235122147685LL * (uint64_t)itime, &seed); ensemble_params_t params; EnsembleParams_Fill(pressure, beta, ¶ms); // initialize elongations and momenta using single-site probability density, Eq. (2.11) EquilibrateCanonical(¶ms, &seed, &f); // current mean values double r_mean = 0; // mean of r's (elongations), remains constant in time double p_mean = 0; // mean momentum double e_mean = 0; // mean energy for (i = 0; i < NUM_SITES; i++) { const lattpoint_t *point = &f.pts[i]; r_mean += point->r; p_mean += point->p; e_mean += LattPoint_Energy(point); } r_mean /= NUM_SITES; p_mean /= NUM_SITES; e_mean /= NUM_SITES; //e_mean -= 0.5 * square(p_mean); // internal energy per particle // compare with stochastic expectation values double r_avr = AverageElongation(pressure, beta); double p_avr = 0; double e_avr = AverageEnergy(pressure, beta); printf("elongation mean: %g, stochastic average: %g\n", r_mean, r_avr); printf("momentum mean: %g, stochastic average: %g\n", p_mean, p_avr); printf("energy mean: %g, stochastic average: %g\n", e_mean, e_avr); } // event table event_table_t tab; assert(NUM_SLOTS == 128/*64*/); EventTable_Allocate(0.01, &tab); // dt, table printf("event table number of slots: %d, slot interval dt: %g\n", NUM_SLOTS, tab.dt); // time period const double period = NUM_SLOTS * tab.dt; printf("event table time period: %g\n", period); // spatial correlation structure spatial_correlation_t scorr; SpatialCorrelation_Allocate(&scorr); // lattice point data pointdata_t data_ref[NUM_SITES]; pointdata_t data_cur[NUM_SITES]; // actual covariance matrix cov_mat_t *cov = malloc(NUM_SITES * sizeof(cov_mat_t)); // initial kinetic and potential energy double en0 = Field_Energy(&f); printf("initial energy: %g\n", en0); // start timer clock_t t_start = clock(); // collect initial collision events CollectEvents(&f, &tab); for (i = 0; i < nsweeps; i++) // repeat several sweeps { // store elongation and momentum, and calculate energies of field variables for (j = 0; j < NUM_SITES; j++) { const lattpoint_t *point = &f.pts[j]; assert(point->t == 0); data_ref[j].r = point->r; // elongation data_ref[j].p = point->p; // momentum data_ref[j].e = LattPoint_Energy(point); // energy } // process events SweepTable(&f, &tab); // synchronize up to period of event table Field_Synchronize(period, &f); // store elongation and momentum, and calculate energies of field variables for (j = 0; j < NUM_SITES; j++) { const lattpoint_t *point = &f.pts[j]; assert(point->t == period); data_cur[j].r = point->r; // elongation data_cur[j].p = point->p; // momentum data_cur[j].e = LattPoint_Energy(point); // energy } // collect and accumulate spatial correlations (for time offset 'period') SpatialCorrelation_Collect(data_ref, data_cur, &scorr); // subtract 'period' from all timing events GlobalTimeshift(period, &f, &tab); // correspondingly add 'period' to time offset of event log #ifdef _DEBUG event_log.time_offset += period; #endif } clock_t t_end = clock(); printf("finished simulation, simulation time: %g, CPU time: %g\n", nsweeps * period, (double)(t_end - t_start) / CLOCKS_PER_SEC); // divide by 'nsweeps' SpatialCorrelation_ScalarMultiply(1.0/nsweeps, &scorr); // calculate covariance matrix CalculateCovariance(&scorr, cov); // save to disk printf("saving covariance matrix to disk...\n"); WriteData("../test/simulation_test_cov.dat", cov, sizeof(cov_mat_t), NUM_SITES, false); // final kinetic and potential energy double en1 = Field_Energy(&f); printf("final energy: %g\n", en1); printf("energy difference: %g (should be zero)\n", en1 - en0); #ifdef _DEBUG printf("total number of events: %i\n", event_log.num); // save event data to disk i = 0; event_node_t *node = event_log.first; double *evtime = malloc(event_log.num * sizeof(double)); int *eviprt = malloc(event_log.num * sizeof(int)); int *evtype = malloc(event_log.num * sizeof(int)); while (node != NULL) { evtime[i] = node->ev.time; eviprt[i] = node->ev.iprt; evtype[i] = (int)node->ev.type; node = node->next; i++; } assert(i == event_log.num); // save event data to disk WriteData("../test/simulation_test_event_time.dat", evtime, sizeof(double), event_log.num, false); WriteData("../test/simulation_test_event_iprt.dat", eviprt, sizeof(int), event_log.num, false); WriteData("../test/simulation_test_event_type.dat", evtype, sizeof(int), event_log.num, false); // clean up free(evtype); free(eviprt); free(evtime); EventLog_Delete(&event_log); #endif // clean up free(cov); SpatialCorrelation_Delete(&scorr); EventTable_Delete(&tab); fftw_cleanup(); return 0; }
int main(int argc, const char* argv[]) { unsigned int ic, is, ip, ir, it; const double pressure = 1.2; // pressure const double beta = 2.0; // inverse temperature #define NUM_SPATIAL_CORR 3 // number of time points at which spatial correlations are collected // cumulative number of 'sweeps' of the event table const unsigned int nsweeps[NUM_SPATIAL_CORR] = { 256, 512, 1024 }; printf("pressure: %g\n", pressure); printf("beta: %g\n", beta); printf("N: %i\n", NUM_SITES); printf("number of sweeps of the event table: %i\n", nsweeps[NUM_SPATIAL_CORR-1]); // check number of input arguments if (argc != 3) { fprintf(stderr, "syntax: %s <number of cycles> <number of samples per cycle>\n", argv[0]); return -1; } // number of cycles unsigned int ncycles = atoi(argv[1]); printf("number of cycles: %i\n", ncycles); // number of samples per cycle unsigned int nsamples = atoi(argv[2]); printf("number of samples per cycle: %i\n", nsamples); // enable run-time memory check for debug builds #if defined(_WIN32) & (defined(DEBUG) | defined(_DEBUG)) _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif // UNIX time unsigned int itime = (unsigned int)time(NULL); printf("itime: %i\n", itime); // trying to create output directory corresponding to 'itime' char path[1024]; sprintf(path, "../output/fields/sim_%i", itime); while (makedir(path) < 0) { printf("cannot create output directory '%s', changing 'itime'...\n", path); #ifdef _WIN32 Sleep(15000); #else sleep(15); #endif itime += (clock() % 16) + 15; sprintf(path, "../output/fields/sim_%i", itime); } printf("created output directory '%s'...\n", path); // random generator seed; multiplicative constant from Pierre L'Ecuyer's paper randseed_t seed; Random_SeedInit(1865811235122147685LL * (uint64_t)itime, &seed); // canonical ensemble parameters ensemble_params_t params; EnsembleParams_Fill(pressure, beta, ¶ms); // lattice field field_t f; Field_Create(&f); // event table event_table_t tab; EventTable_Allocate(1.0/NUM_SLOTS, &tab); // dt, table printf("event table number of slots: %i, slot interval dt: %g, events per slot: %i\n", NUM_SLOTS, tab.dt, EVENTS_PER_SLOT); // time period const double period = NUM_SLOTS * tab.dt; printf("event table time period: %g\n", period); printf("maximum simulation time: %g\n", nsweeps[NUM_SPATIAL_CORR-1] * period); // create subdirectories for saving files for (ir = 0; ir < NUM_SPATIAL_CORR; ir++) { sprintf(path, "../output/fields/sim_%i/t%i", itime, (int)(nsweeps[ir]*period)); if (makedir(path) < 0) { fprintf(stderr, "'mkdir(%s)' failed.\n", path); return -1; } } // spatial correlation structure spatial_correlation_t scorr[NUM_SPATIAL_CORR]; for (ir = 0; ir < NUM_SPATIAL_CORR; ir++) { SpatialCorrelation_Allocate(&scorr[ir]); } // lattice point data pointdata_t data_ref[NUM_SITES]; pointdata_t data_cur[NUM_SITES]; // start timer clock_t t_start = clock(); for (ic = 0; ic < ncycles; ic++) { printf("cycle %i\n", ic + 1); for (is = 0; is < nsamples; is++) { // initialize elongations and momenta using single-site probability density, Eq. (2.11) EquilibrateCanonical(¶ms, &seed, &f); // initial energy double en0 = Field_Energy(&f); //printf("initial energy: %g\n", en0); // initial field: store elongation and momentum, and calculate energies of field variables for (ip = 0; ip < NUM_SITES; ip++) { const lattpoint_t *point = &f.pts[ip]; assert(point->t == 0); data_ref[ip].r = point->r; // elongation data_ref[ip].p = point->p; // momentum data_ref[ip].e = LattPoint_Energy(point); // energy } // collect initial collision events CollectEvents(&f, &tab); // run actual simulation for (ir = 0; ir < NUM_SPATIAL_CORR; ir++) { for (it = (ir == 0 ? 0 : nsweeps[ir-1]); it < nsweeps[ir]; it++) // repeat several sweeps { // process events SweepTable(&f, &tab); // synchronize up to period of event table //Field_Synchronize(period, &f); // subtract 'period' from all timing events GlobalTimeshift(period, &f, &tab); // correspondingly add 'period' to time offset of event log #ifdef _DEBUG event_log.time_offset += period; #endif } // 'period' has already been subtracted Field_Synchronize(0, &f); // current field: store elongation and momentum, and calculate energies of field variables for (ip = 0; ip < NUM_SITES; ip++) { const lattpoint_t *point = &f.pts[ip]; assert(point->t == 0); data_cur[ip].r = point->r; // elongation data_cur[ip].p = point->p; // momentum data_cur[ip].e = LattPoint_Energy(point); // energy } // collect and accumulate spatial correlations (for time offset 'nsweeps[ir] * period') SpatialCorrelation_Collect(data_ref, data_cur, &scorr[ir]); } // time point loop // final energy double en1 = Field_Energy(&f); //printf("final energy: %g\n", en1); //printf("energy difference: %g (should be zero)\n", en1 - en0); if (fabs(en1 - en0) > 1e-10) { fprintf(stderr, "warning: energy seems not to be conserved, difference: %g\n", fabs(en1 - en0)); } // reset event table EventTable_Reset(&tab); #ifdef _DEBUG // reset event log EventLog_Delete(&event_log); #endif } // sample loop for (ir = 0; ir < NUM_SPATIAL_CORR; ir++) { // divide by 'nsamples' SpatialCorrelation_ScalarMultiply(1.0 / nsamples, &scorr[ir]); // save to disk const int timepoint = (int)(nsweeps[ir]*period); printf("saving averages required for correlators at time %i to disk...\n", timepoint); sprintf(path, "../output/fields/sim_%i/t%i/sim_%i_t%i_ns%i_avr0_%04d.dat", itime, timepoint, itime, timepoint, nsamples, ic); WriteData(path, &scorr[ir].avr[0], sizeof(pointdata_t), 1, false); sprintf(path, "../output/fields/sim_%i/t%i/sim_%i_t%i_ns%i_avr1_%04d.dat", itime, timepoint, itime, timepoint, nsamples, ic); WriteData(path, &scorr[ir].avr[1], sizeof(pointdata_t), 1, false); sprintf(path, "../output/fields/sim_%i/t%i/sim_%i_t%i_ns%i_sqrs_%04d.dat", itime, timepoint, itime, timepoint, nsamples, ic); WriteData(path, scorr[ir].sqr, sizeof(cov_mat_t), NUM_SITES, false); // reset spatial correlation structure SpatialCorrelation_Reset(&scorr[ir]); } } // cycle loop clock_t t_end = clock(); double cpu_time = (double)(t_end - t_start) / CLOCKS_PER_SEC; printf("finished simulation, CPU time: %g, average CPU time per run: %g\n", cpu_time, cpu_time / (ncycles * nsamples)); // clean up for (ir = 0; ir < NUM_SPATIAL_CORR; ir++) { SpatialCorrelation_Delete(&scorr[ir]); } EventTable_Delete(&tab); fftw_cleanup(); return 0; }
int main(int argc, const char* argv[]) { unsigned int ic, is, im, ip, it; const double pressure = 2.0; // pressure const double beta = 0.5; // inverse temperature const double mass[2] = { 1, 3 }; // alternating masses const double c_sound = 1.73205080756887729; // speed of sound for these concrete pressure, beta and mass values: sqrt(3) const double ell_avr = AverageElongation(pressure, beta); const double en_avr = AverageEnergy(beta); const double matR_0r = 0.8164965809277260327; // the (0,r) entry of the R matrix (normal mode 0 and physical coordinate elongation 'r'): sqrt(2/3) const double matR_s6 = 0.408248290463863016; // the (sigma,r), (0,e) and (sigma,e) entries of the R matrix (physical elongation 'r' or energy coordinate 'e'): 1/sqrt(6) const double matR_1p = 0.353553390593273762; // the (1,p) entry of the R matrix (normal mode 1 and physical momentum coordinate 'p'): 1/(2*sqrt(2)) // number of 'sweeps' of the event table, i.e., current is integrated up to t = nsweeps*period where 'period' is the event table time period const unsigned int nsweeps = 1024; // inverse bin width for time-integrated current const double inv_bin_width_J = 2; // number of bins for time-integrated current #define NUM_JINT_BINS 2048 #define MASK_JINT_BIN (NUM_JINT_BINS - 1) printf("pressure: %g\n", pressure); printf("beta: %g\n", beta); printf("average elongation: %g\n", ell_avr); printf("average energy: %g\n", en_avr); printf("N: %i\n", NUM_SITES); printf("maximum time in units of event table time period: %i\n", nsweeps); printf("bin width for time-integrated current: %g, number of bins: %i\n", 1/inv_bin_width_J, NUM_JINT_BINS); // check number of input arguments if (argc != 3) { fprintf(stderr, "syntax: %s <number of cycles> <number of samples per cycle>\n", argv[0]); return -1; } // number of cycles unsigned int ncycles = atoi(argv[1]); printf("number of cycles: %i\n", ncycles); // number of samples per cycle unsigned int nsamples = atoi(argv[2]); printf("number of samples per cycle: %i\n", nsamples); // enable run-time memory check for debug builds #if defined(_WIN32) & (defined(DEBUG) | defined(_DEBUG)) _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif // UNIX time unsigned int itime = (unsigned int)time(NULL); printf("itime: %i\n", itime); // trying to create output directory corresponding to 'itime' char path[1024]; sprintf(path, "../output/current_Jsite/sim_%i", itime); while (makedir(path) < 0) { printf("cannot create output directory '%s', changing 'itime'...\n", path); #ifdef _WIN32 Sleep(15000); #else sleep(15); #endif itime += (clock() % 16) + 15; sprintf(path, "../output/current_Jsite/sim_%i", itime); } printf("created output directory '%s'...\n", path); // random generator seed; multiplicative constant from Pierre L'Ecuyer's paper randseed_t seed; Random_SeedInit(1865811235122147685LL * (uint64_t)itime, &seed); // lattice field field_t f; Field_Create(mass, &f); // event table event_table_t tab; EventTable_Allocate(1.0/NUM_SLOTS, &tab); // dt, table printf("event table number of slots: %i, slot interval dt: %g, events per slot: %i\n", NUM_SLOTS, tab.dt, EVENTS_PER_SLOT); // time period const double period = NUM_SLOTS * tab.dt; printf("event table time period: %g\n", period); const double t_max = nsweeps * period; printf("maximum simulation time: %g\n", t_max); // c_sound * t const double ct = c_sound * t_max; // rounded version const unsigned int cti = (unsigned int)round(ct); // spatial correlation structure spatial_correlation_t scorr; SpatialCorrelation_Allocate(&scorr); current_t *J_int = fftw_malloc(NUM_SITES * sizeof(current_t)); currnrm_t *J_inr = fftw_malloc(NUM_SITES * sizeof(currnrm_t)); current_t *F_int = fftw_malloc(NUM_SITES * sizeof(current_t)); // start timer clock_t t_start = clock(); for (ic = 0; ic < ncycles; ic++) { printf("cycle %i\n", ic + 1); // sort time-integrated current values transformed to normal modes into bins unsigned long long J_int_counts[3][NUM_JINT_BINS] = { 0 }; for (is = 0; is < nsamples; is++) { // total time-integrated currents in physical coordinates for each lattice site memset(J_int, 0, NUM_SITES * sizeof(current_t)); // initialize elongations and momenta using single-site probability density, Eq. (2.11) EquilibrateCanonical(pressure, beta, &seed, &f); // initial energy double en0 = Field_Energy(&f); //printf("initial energy: %g\n", en0); // spatial integrals over field variables with length c*t memset(F_int, 0, NUM_SITES * sizeof(current_t)); for (ip = 0; ip < cti; ip++) { F_int[0].r += f.pts[(0 - ip) & SITE_MASK].r - ell_avr; F_int[0].p += f.mass[ip & 1] * f.pts[(0 - ip) & SITE_MASK].v; F_int[0].e += LattPoint_Energy(f.mass[ip & 1], &f.pts[(0 - ip) & SITE_MASK]) - en_avr; } for (ip = 1; ip < NUM_SITES; ip++) { F_int[ip].r = F_int[ip - 1].r + f.pts[ip].r - f.pts[(ip - cti) & SITE_MASK].r; F_int[ip].p = F_int[ip - 1].p + f.mass[ip & 1] * f.pts[ip].v - f.mass[(ip - cti) & 1] * f.pts[(ip - cti) & SITE_MASK].v; F_int[ip].e = F_int[ip - 1].e + LattPoint_Energy(f.mass[ip & 1], &f.pts[ip]) - LattPoint_Energy(f.mass[(ip - cti) & 1], &f.pts[(ip - cti) & SITE_MASK]); } // collect initial collision events CollectEvents(&f, &tab); // run actual simulation for (it = 0; it < nsweeps; it++) { // process events and record current current_t J[NUM_SITES]; SweepTableJSite(&f, &tab, J); // integrate currents over time; subtract theoretical average value for (ip = 0; ip < NUM_SITES; ip++) { J_int[ip].r += J[ip].r; J_int[ip].p += J[ip].p - period*pressure; J_int[ip].e += J[ip].e; } // subtract 'period' from all timing events GlobalTimeshift(period, &f, &tab); // correspondingly add 'period' to time offset of event log #ifdef _DEBUG event_log.time_offset += period; #endif } // time point loop // complete velocity integration for elongation current; 'period' has already been subtracted for (ip = 0; ip < NUM_SITES; ip++) { lattpoint_t *point = &f.pts[ip]; J_int[ip].r -= (0 - point->t) * point->v; } // not required here // Field_Synchronize(0, &f); // transform integrated current values to normal modes for (ip = 0; ip < NUM_SITES; ip++) { // transform to normal modes -1, 0, 1 J_inr[ip].m[0] = -matR_s6 * J_int[ip].r - matR_1p * J_int[ip].p + matR_s6 * J_int[ip].e; // mode -1 J_inr[ip].m[1] = matR_0r * J_int[ip].r + matR_s6 * J_int[ip].e; // mode 0 J_inr[ip].m[2] = -matR_s6 * J_int[ip].r + matR_1p * J_int[ip].p + matR_s6 * J_int[ip].e; // mode 1 } // collect and accumulate spatial time-integrated current auto-correlations SpatialCorrelation_Collect((pointdata_t *)J_inr, (pointdata_t *)J_inr, &scorr); // subtract spatial integrals over field variables at t = 0 from sound modes and sort into bins for (ip = 0; ip < NUM_SITES; ip++) { // correspondingly transform integrals over field variables unsigned int iq = (ip + cti) & SITE_MASK; // integrate "backwards" double Fm1 = -matR_s6 * F_int[iq].r - matR_1p * F_int[iq].p + matR_s6 * F_int[iq].e; double F_1 = -matR_s6 * F_int[ip].r + matR_1p * F_int[ip].p + matR_s6 * F_int[ip].e; // subtract spatial integrals over field variables at t = 0 from sound modes J_inr[ip].m[0] += Fm1; // mode -1 J_inr[ip].m[2] -= F_1; // mode 1 for (im = 0; im < 3; im++) // for each mode... { // bit masking modulo operation works for negative integers also int ib = (int)floor(J_inr[ip].m[im] * inv_bin_width_J); if (-NUM_JINT_BINS/2 <= ib && ib < NUM_JINT_BINS/2) { J_int_counts[im][ib & MASK_JINT_BIN]++; } } } // final energy double en1 = Field_Energy(&f); //printf("final energy: %g\n", en1); //printf("energy difference: %g (should be zero)\n", en1 - en0); if (fabs(en1 - en0) > 1e-10) { fprintf(stderr, "warning: energy seems not to be conserved, difference: %g\n", fabs(en1 - en0)); } // reset event table EventTable_Reset(&tab); #ifdef _DEBUG printf("total number of events: %i\n", event_log.num); printf("average time difference between events: %g\n", nsweeps * period / event_log.num); // reset event log EventLog_Delete(&event_log); #endif } // sample loop // divide by 'nsamples' SpatialCorrelation_ScalarMultiply(1.0 / nsamples, &scorr); // save to disk printf("saving histograms and spatial correlations of time-integrated currents to disk...\n"); for (im = 0; im < 3; im++) // for each mode... { const char *mode_names[3] = { "N", "0", "1" }; sprintf(path, "../output/current_Jsite/sim_%i/sim_%i_ns%i_J_int_mode%s_hist_%04d.dat", itime, itime, nsamples, mode_names[im], ic); WriteData(path, J_int_counts[im], sizeof(unsigned long long), NUM_JINT_BINS, false); } // scorr.avr[1] same as scorr.avr[0] sprintf(path, "../output/current_Jsite/sim_%i/sim_%i_ns%i_J_int_corr_avr_%04d.dat", itime, itime, nsamples, ic); WriteData(path, &scorr.avr[0], sizeof(pointdata_t), 1, false); sprintf(path, "../output/current_Jsite/sim_%i/sim_%i_ns%i_J_int_corr_sqr_%04d.dat", itime, itime, nsamples, ic); WriteData(path, scorr.sqr, sizeof(cov_mat_t), NUM_SITES, false); // reset spatial correlation structure SpatialCorrelation_Reset(&scorr); } // cycle loop clock_t t_end = clock(); double cpu_time = (double)(t_end - t_start) / CLOCKS_PER_SEC; printf("finished simulation, CPU time: %g, average CPU time per run: %g\n", cpu_time, cpu_time / (ncycles * nsamples)); // clean up fftw_free(J_inr); fftw_free(F_int); fftw_free(J_int); SpatialCorrelation_Delete(&scorr); EventTable_Delete(&tab); fftw_cleanup(); return 0; }