// RESULTS.C // © 2021 Peter J. Meyer #include "iss.h" #include <process.h> // #define WR_ST_DEV_AUTOCORRELATON Now in ISS_DEF.H #define WR_LOG_ST_DEV_MAGNETISM false // #define ALWAYS_WRITE_AUTOCORRELATION true #define WRITE_SYSTEM_DATA false static double mean_magn, std_dev_magn; static double mean_bc, std_dev_bc; static double mean_ie, std_dev_ie; static double mean_sh, std_dev_sh; #if TIMING_DIAGNOSTICS extern long create_v_cluster_clock; extern long flip_sw_clusters_clock; extern long flip_sw_cluster_clock; extern long another_sw_spin_clock; extern long flip_sw_spin_clock; #endif extern unsigned int num_times_adjust_index_called; extern unsigned int num_times_get_nn_sites_called; extern unsigned int num_times_get_nn_site_in_dir_called; extern unsigned int num_virtual_bonds_opened; extern unsigned int total_num_opened_bonds; static void write_lattice_info(FILE *of); static void write_samples_info(FILE *of, int multiple_temperatures_summary); static void calculate_magnetization_results(int pc, FILE *of); static void calculate_binder_cumulant(int pc, FILE *of); static void calculate_ie_sh_results(int pc, FILE *of); extern void write_timeslice_values(FILE *of, int w); // TS_VALS.C /*----------------------------------*/ void write_equilibration_results(void) { int i, j; int w=9; int ch; int temp_written=false; double crit_temp; FILE *of; #if WRITE_SYSTEM_DATA unsigned int nmcs; #endif while ( !open_file(output_filepath,"a+t",&of) ) // "a+", append, in case output from multiple runs with a range of temperatures. // file already truncated (if previously existing) in set_up_filenames() in FILE_IO.C. { printf("\n\aCannot open output file %s.",output_filepath); printf("\nPerhaps this file is already open? Retry or quit? (R|Q) "); ch = getche(); if ( ch == 'Q' || ch == 'q' ) exit(1); } fprintf(of,"Run began at %s %s\n",run_start_date,run_start_time); if ( escape_key_termination ) fprintf(of,"\nEscape key was pressed: run probably not completed.\n"); if ( stop_on_next_temperature && ( temperature_num+1 != num_temperatures ) ) fprintf(of,"\nRequest was made to stop on next temperature." "\nSome temperatures not done.\n"); // This run data is very similar to that given by display_startup_info(). fprintf(of,"\ninput file: %s",input_filepath); if ( num_input_files > 1 ) fprintf(of," (#%d of %d)",input_file_num+1,num_input_files); fprintf(of,"\noutput file: %s",output_filepath); #if SAVE_MEASUREMENTS fprintf(of,"\nmeasurements file: %s",measurements_filepath); #endif fprintf(of,"\n"); write_lattice_info(of); sprintf(temp,"%.6f",temperature); remove_trailing_zeros(temp); fprintf(of,"\ntemperature: %s ",temp); // If this is the critical temperature of the current model then show this. if ( ( crit_temp = get_critical_temperature() ) != -1 ) { if ( temperature == crit_temp ) { if ( model_is_ising ) fprintf(of,"(Ising %s cr. temp.)",lattice_types[l_type].name); else // model is q-state Potts fprintf(of,"(%dd %d-state Potts cr. temp.)",dimensionality,q); } else fprintf(of," = %.3f%% of Tc",100*temperature/crit_temp); } if ( multiple_temperatures_specified ) fprintf(of," (#%d of %d)",temperature_num+1,num_temperatures); fprintf(of,"\ndynamics: %s",dynamics_types[d_type][1]); if ( dynamics_is_swendsen_wang || dynamics_is_wolff ) fprintf(of," (p = %.5f)",v_bond_probability); else fprintf(of,"\nspin selection: %s",spin_selns[ss_type][1]); fprintf(of,"\ninitial magnetization: %.5f\n",initial_magnetization); write_samples_info(of,false); if ( absolute_magnetization_requested || !timeslice_values_requested ) fprintf(of,"\n"); if ( absolute_magnetization_requested && timeslice_values_requested ) fprintf(of,"\nAbsolute magnetization requested."); if ( timeslice_values_requested ) write_timeslice_values(of,w); // TS_VALS.C calculate_magnetization_results(percentage_range_for_mean,of); if ( multiple_temperatures_specified ) { multiple_temperature_results[temperature_num][0][0] = mean_magn; multiple_temperature_results[temperature_num][0][1] = std_dev_magn; } if ( binder_cumulant_measured ) { calculate_binder_cumulant(percentage_range_for_mean,of); if ( multiple_temperatures_specified ) { multiple_temperature_results[temperature_num][1][0] = mean_bc; multiple_temperature_results[temperature_num][1][1] = std_dev_bc; } } if ( internal_energy_measured ) { calculate_ie_sh_results(percentage_range_for_mean,of); if ( multiple_temperatures_specified ) { multiple_temperature_results[temperature_num][2][0] = mean_ie; multiple_temperature_results[temperature_num][2][1] = std_dev_ie; multiple_temperature_results[temperature_num][3][0] = mean_sh; multiple_temperature_results[temperature_num][3][1] = std_dev_sh; } } fprintf(of,"\nRun ended at %s %s",run_end_date,run_end_time); fprintf(of,"\nRun time = "); if ( run_time < 60 ) fprintf(of,"%.2f seconds",run_time); else { fprintf(of,"%s",seconds_to_time_str((unsigned long)run_time,temp)); fprintf(of," (%lu seconds)",(unsigned long)run_time); } if ( pause_time ) fprintf(of,"\nexcluding pause time of %s seconds.",ultoa_commas(pause_time,temp)); #if TIMING_DIAGNOSTICS fprintf(of,"\nTime spent in cluster-creation function = %.2f seconds (%.2f%%)", (double)create_v_cluster_clock/CLOCKS_PER_SEC, 100*(double)create_v_cluster_clock/CLOCKS_PER_SEC/run_time); fprintf(of,"\nTime spent in clusters-flip function = %.2f seconds (%.2f%%)", (double)flip_sw_clusters_clock/CLOCKS_PER_SEC, 100*(double)flip_sw_clusters_clock/CLOCKS_PER_SEC/run_time); fprintf(of,"\nTime spent in cluster-flip function = %.2f seconds (%.2f%%)", (double)flip_sw_cluster_clock/CLOCKS_PER_SEC, 100*(double)flip_sw_cluster_clock/CLOCKS_PER_SEC/run_time); fprintf(of,"\nTime spent in flip_sw_spin function = %.2f seconds (%.2f%%)", (double)flip_sw_spin_clock/CLOCKS_PER_SEC, 100*(double)flip_sw_spin_clock/CLOCKS_PER_SEC/run_time); fprintf(of,"\nTime spent in another_sw_spin = %.2f seconds (%.2f%%)", (double)another_sw_spin_clock/CLOCKS_PER_SEC, 100*(double)another_sw_spin_clock/CLOCKS_PER_SEC/run_time); fprintf(of,"\n"); #endif #if WRITE_SYSTEM_DATA if ( dynamics_is_swendsen_wang ) { fprintf(of,"\nAverage number of SW virtual bonds opened per sweep per sample = %s", ultoa_commas((unsigned long)(num_virtual_bonds_opened/num_sweeps/num_samples),temp)); fprintf(of,"\nAverage percentage of open bonds becoming SW virtual bonds = %.2f%%", 100*(double)num_virtual_bonds_opened/num_sweeps/num_samples/total_num_opened_bonds); // NEEDS CHECKING } fprintf(of,"\nNumber of times get_nn_sites() called = %s", ultoa_commas(num_times_get_nn_sites_called,temp)); fprintf(of,"\nNumber of times get_nn_site_in_dir() called = %s", ultoa_commas(num_times_get_nn_site_in_dir_called,temp)); fprintf(of,"\nNumber of times adjust_index() called = %s", ultoa_commas(num_times_adjust_index_called,temp)); fprintf(of,"\n"); nmcs = (num_time_slices-1)*step_length + 1; if ( !num_spin_visits && !num_spin_visits_overflow ) fprintf(of,"\nNo spins were visited."); else { if ( !num_spin_visits_overflow ) { fprintf(of,"\n%.2f%% of %s spin visits resulted in spin flips (%s spin flips).", (num_spin_flips*(double)100)/num_spin_visits, ultoa_commas((unsigned long)num_spin_visits,temp), ultoa_commas((unsigned long)num_spin_flips,temp2)); fprintf(of,"\nSpin flips per spin per sample per timestep = %.4f", (double)num_spin_flips/num_samples/num_spins/nmcs); if ( run_time > 0 ) fprintf(of,"\nNumber of spin visits per second = %s", ultoa_commas((unsigned long)(num_spin_visits/run_time),temp)); } else { fprintf(of,"\n%.2f%% of %.0f million spins visited were flipped " "(%.0f million spins flipped).", ((num_spin_flips+pow(2,32)*num_spin_flips_overflow)*100)/ (num_spin_visits+pow(2,32)*num_spin_visits_overflow), (num_spin_visits+pow(2,32)*num_spin_visits_overflow)/1e6, (num_spin_flips+pow(2,32)*num_spin_flips_overflow)/1e6); fprintf(of,"\nSpin flips per spin per sample per timestep = %.4f", (num_spin_flips+pow(2,32)*num_spin_flips_overflow) /num_samples/num_spins/nmcs); fprintf(of,"\nNumber of spin visits per second = %s",ultoa_commas( (unsigned long)((num_spin_visits+pow(2,32)*num_spin_visits_overflow) /run_time),temp)); } if ( dynamics_is_swendsen_wang || dynamics_is_wolff ) { fprintf(of,"\nTotal number of clusters traced = "); if ( num_clusters_traced_overflow ) fprintf(of,"%.0f",num_clusters_traced+pow(2,32)*num_clusters_traced_overflow); else fprintf(of,"%s",ultoa_commas((unsigned long)num_clusters_traced,temp)); fprintf(of,"\nMaximum cluster size = %s ", ultoa_commas((unsigned long)max_cluster_size,temp)); fprintf(of,"(%.2f%% of occupied sites).", ((double)max_cluster_size*100)/num_spins); fprintf(of,"\nAverage size of clusters traced = "); fprintf(of,"%.4f", (num_spin_visits+pow(2,32)*num_spin_visits_overflow) /(num_clusters_traced+pow(2,32)*num_clusters_traced_overflow)); fprintf(of,"\nAverage number of clusters per sweep = %.4f", (num_clusters_traced+pow(2,32)*num_clusters_traced_overflow) /(num_sweeps+pow(2,32)*num_sweeps_overflow)); if ( dynamics_is_wolff ) fprintf(of,"\nAverage number of spins visited per sweep per spin = %.4f", (num_spin_visits/(num_sweeps+pow(2,32)*num_sweeps_overflow)) /num_spins); } if ( stack_size ) write_stack_data(of); // STACK.C } #endif if ( num_spin_visits || num_spin_visits_overflow ) { if ( (unsigned long)NUM_PRNG1_CALLS() < 2e9 ) fprintf(of,"\n%s was called %s times.",PRNG1_NAME, ultoa_commas((unsigned long)NUM_PRNG1_CALLS(),temp)); else fprintf(of,"\n%s was called %s million times.",PRNG1_NAME, ultoa_commas((unsigned long)(NUM_PRNG1_CALLS()/1e6),temp)); if ( seed < 100000 ) fprintf(of," Random seed = %u",seed); fprintf(of,"\n"); if ( PRNG1_PERIOD_EXCEEDED() ) fprintf(of,"\nThe period for %s was exceeded.\n",PRNG1_NAME); } if ( multiple_temperatures_specified ) fprintf(of,"\n--------------------------------------------------------\n\n"); if ( multiple_temperatures_specified && ( final_temperature || escape_key_termination || stop_on_next_temperature ) ) { write_lattice_info(of); fprintf(of,"\ndynamics: %s",dynamics_types[d_type][1]); write_samples_info(of,true); // Print multiple results. fprintf(of,"\n %-*s%-*s",w+1,"Temp.",2*(w+1),"Magnetization"); if ( binder_cumulant_measured ) fprintf(of,"%-*s",2*(w+1),"Binder cumulant"); if ( internal_energy_measured ) fprintf(of,"%-*s%-*s",2*(w+1),"Internal Energy",2*(w+1),"Specific heat"); fprintf(of,"\n%*s",w+1,""); fprintf(of,"%*s%*s",w+1,"mean",w+1,"std dev"); if ( binder_cumulant_measured ) fprintf(of,"%*s%*s",w+1,"mean",w+1,"std dev"); if ( internal_energy_measured ) for ( j=2; j<=3; j++ ) fprintf(of,"%*s%*s",w+1,"mean",w+1,"std dev"); for ( i=0; i<num_temperatures; i++ ) { fprintf(of,"\n%3d%*.6f",i+1,w+1,temperatur[i]); fprintf(of,"%*.6f",w+1,multiple_temperature_results[i][0][0]); if ( multiple_temperature_results[i][0][1] == NON_EXISTENT ) fprintf(of,"%*s",w+1,""); else fprintf(of,"%*.6f",w+1,multiple_temperature_results[i][0][1]); if ( binder_cumulant_measured ) fprintf(of,"%*.6f%*.6f",w+1,multiple_temperature_results[i][1][0], w+1,multiple_temperature_results[i][1][1]); if ( internal_energy_measured ) { for ( j=2; j<=3; j++ ) fprintf(of,"%*.6f%*.6f",w+1,multiple_temperature_results[i][j][0], w+1,multiple_temperature_results[i][j][1]); } } fprintf(of,"\n"); } fclose(of); if ( final_temperature || escape_key_termination || stop_on_next_temperature ) spawnlp(P_NOWAIT,"notepad.exe","notepad.exe",output_filepath,NULL); } /*------------------------------------*/ static void write_lattice_info(FILE *of) { fprintf(of,"\nmodel: "); if ( model_is_q_state_potts ) fprintf(of,"%d-state Potts",q); else fprintf(of,"%s",models[m_type][1]); fprintf(of,"\ndimensionality: %d",dimensionality); fprintf(of,"\nlattice type: %s",lattice_types[l_type].name); if ( direction_table_is_parity_dependent && MAJOR_AXIS_SPECIFICATION_PERMITTED ) fprintf(of,"\nmajor axis: %d",major_axis); fprintf(of,"\nlattice size: %d",size); if ( site_diluted ) fprintf(of,"\nsite concentration: %.3f",site_concentration); else if ( bond_diluted ) fprintf(of,"\nbond concentration: %.3f",bond_concentration); fprintf(of,"\n"); } /*-----------------------------------------------------------------------*/ static void write_samples_info(FILE *of, int multiple_temperatures_summary) { double num_requested; fprintf(of,"\nnumber of configurations: %d",num_configurations); fprintf(of,"\nnumber of spin assignments: %d",num_spin_assignments); fprintf(of,"\nnumber of repetitions: %d",num_repetitions); fprintf(of,"\nnumber of samples: "); if ( num_samples < pow(2,31) ) fprintf(of,"%s",ultoa_commas((unsigned long)num_samples,temp)); else fprintf(of,"%.0f",num_samples); if ( escape_key_termination ) { if ( multiple_temperatures_summary ) fprintf(of,"\nEscape key pressed during temperature #%d",temperature_num+1); else { num_requested = (double)num_configurations*num_spin_assignments*num_repetitions; if ( num_requested < pow(2,31) ) fprintf(of," (of %s requested)",ultoa_commas((unsigned long)num_requested,temp)); else fprintf(of," (of %.0f requested)",num_requested); } } fprintf(of,"\n\nnumber of time slices: %d",num_time_slices); fprintf(of,"\nstep length: %d",step_length); } // Average the mean and the standard deviation // of the magnetization over the last pc% of time slices. /*---------------------------------------------------------*/ static void calculate_magnetization_results(int pc, FILE *of) { double sum_magn, sum_std_dev; int j, pr; int to_ts = num_time_slices - 1; int from_ts = 1 + ((num_time_slices-1)*(100-pc))/100; int num_values = to_ts-from_ts+1; if ( from_ts > to_ts - 1 ) return; fprintf(of, "\nMean and standard deviation of the %smagnetization" "\nover the last %d%% of timeslices, i.e., timeslices %d through %d.", ( absolute_magnetization_requested ? "absolute " : "" ), pc,from_ts,to_ts); fprintf(of,"\n%s per spin", ( absolute_magnetization_requested ? "Absolute magnetization" : "Magnetization" )); fprintf(of,"\n%-9s%-9s%-9s%-9s","mean","std.dev.","m-sd","m+sd"); sum_magn = sum_std_dev = 0.0; for ( j=from_ts; j<=to_ts; j++ ) { sum_magn += magnetization[j][0]; if ( magnetization[j][1] == NON_EXISTENT ) std_dev_magn = NON_EXISTENT; else if ( std_dev_magn != NON_EXISTENT ) sum_std_dev += magnetization[j][1]; } mean_magn = sum_magn/num_values; if ( std_dev_magn != NON_EXISTENT ) std_dev_magn = sum_std_dev/num_values; for ( pr=5; pr>=2; pr--) { fprintf(of,"\n%-9.*f",pr,mean_magn); if ( std_dev_magn != NON_EXISTENT ) fprintf(of,"%-9.*f%-9.*f%-9.*f",pr,std_dev_magn, pr,mean_magn-std_dev_magn,pr,mean_magn+std_dev_magn); } fprintf(of,"\n"); } // Average the binder cumulant over the last pc% of time slices // and estimate the std. dev. /*---------------------------------------------------*/ static void calculate_binder_cumulant(int pc, FILE *of) { double sum_bc, sum_sq_dev_bc; int j, pr; int to_ts = num_time_slices - 1; int from_ts = 1 + ((num_time_slices-1)*(100-pc))/100; int num_values = to_ts-from_ts+1; if ( from_ts > to_ts - 1 ) return; fprintf(of,"\nMean and standard deviation of the Binder cumulant" "\nover the last %d%% of timeslices, i.e., timeslices %d through %d.", pc,from_ts,to_ts); fprintf(of,"\nBinder cumulant"); fprintf(of,"\n%-9s%-9s%-9s%-9s","mean","std.dev.","m-sd","m+sd"); sum_bc = 0.0; for ( j=from_ts; j<=to_ts; j++ ) sum_bc += magnetization[j][3]; mean_bc = sum_bc/num_values; sum_sq_dev_bc = 0.0; for ( j=from_ts; j<=to_ts; j++ ) sum_sq_dev_bc += (mean_bc - magnetization[j][3])*(mean_bc - magnetization[j][3]); std_dev_bc = sqrt(sum_sq_dev_bc/num_values); for ( pr=5; pr>=2; pr--) { fprintf(of,"\n%-9.*f%-9.*f%-9.*f%-9.*f", pr,mean_bc,pr,std_dev_bc, pr,mean_bc-std_dev_bc,pr,mean_bc+std_dev_bc); } fprintf(of,"\n"); } // Average the mean and the standard deviation of the internal energy // and the mean of the specific heat over the last pc% of time slices. // Estimate standard deviation of specific heat from std dev of mean value. /*-------------------------------------------------*/ static void calculate_ie_sh_results(int pc, FILE *of) { double sum_ie, sum_std_dev_ie, sum_sh, sum_sq_dev_sh; int j, pr; int to_ts = num_time_slices - 1; int from_ts = 1 + ((num_time_slices-1)*(100-pc))/100; int num_values = to_ts-from_ts+1; if ( from_ts > to_ts - 1 ) return; fprintf(of,"\nMean and standard deviation of the internal energy and specific heat" "\nover the last %d%% of timeslices, i.e., timeslices %d through %d.", pc,from_ts,to_ts); fprintf(of,"\n%20s%35s","Internal energy per spin","Specific heat per spin"); fprintf(of,"\n%-9s%-9s%-9s%-9s%-3s%-9s%-9s%-9s%-9s", "mean","std.dev.","m-sd","m+sd","|", "mean","std.dev.","m-sd","m+sd"); sum_ie = sum_std_dev_ie = sum_sh = 0.0; for ( j=from_ts; j<=to_ts; j++ ) { sum_ie += internal_energy[j][0]; // internal energy sum_std_dev_ie += internal_energy[j][1]; // std dev of internal energy sum_sh += internal_energy[j][2]; // specific heat } mean_ie = sum_ie/num_values; std_dev_ie = sum_std_dev_ie/num_values; mean_sh = sum_sh/num_values; sum_sq_dev_sh = 0.0; for ( j=from_ts; j<=to_ts; j++ ) sum_sq_dev_sh += (mean_sh - internal_energy[j][2])*(mean_sh - internal_energy[j][2]); std_dev_sh = sqrt(sum_sq_dev_sh/num_values); for ( pr=5; pr>=2; pr--) { fprintf(of,"\n%-9.*f%-9.*f%-9.*f%-9.*f%-3s%-9.*f%-9.*f%-9.*f%-9.*f", pr,mean_ie,pr,std_dev_ie, pr,mean_ie-std_dev_ie,pr,mean_ie+std_dev_ie, "|",pr,mean_sh,pr,std_dev_sh, pr,mean_sh-std_dev_sh,pr,mean_sh+std_dev_sh); } fprintf(of,"\n"); }