Make some changes

- Add new programs
- Add command line args
- Add Usage to guide user on how to use programs
This commit is contained in:
Cory Balaton 2023-12-04 12:36:29 +01:00
parent 1089c2d110
commit 1762fc87ad
No known key found for this signature in database
GPG Key ID: 3E5FCEBFD80F432B
10 changed files with 464 additions and 59 deletions

View File

@ -31,8 +31,8 @@ namespace montecarlo {
* @param cycles The amount of Monte Carlo cycles to do * @param cycles The amount of Monte Carlo cycles to do
* @param filename The file to write to * @param filename The file to write to
* */ * */
void progression(double T, int L, int cycles, void progression(double T, int L, int cycles, const std::string filename,
const std::string filename); int burn_in_time = BURN_IN_TIME);
/** @brief Write the expected values for each Monte Carlo cycles to file. /** @brief Write the expected values for each Monte Carlo cycles to file.
* *
@ -43,7 +43,7 @@ void progression(double T, int L, int cycles,
* @param filename The file to write to * @param filename The file to write to
* */ * */
void progression(double T, int L, int cycles, int value, void progression(double T, int L, int cycles, int value,
const std::string filename); const std::string filename, int burn_in_time = BURN_IN_TIME);
/** @brief Estimate the probability distribution for the energy. /** @brief Estimate the probability distribution for the energy.
* *
@ -52,8 +52,8 @@ void progression(double T, int L, int cycles, int value,
* @param cycles The amount of Monte Carlo cycles to do * @param cycles The amount of Monte Carlo cycles to do
* @param filename The file to write to * @param filename The file to write to
* */ * */
void pd_estimate(double T, int L, int cycles, void pd_estimate(double T, int L, int cycles, const std::string filename,
const std::string filename); int burn_in_time = BURN_IN_TIME);
/** @brief Execute the Metropolis algorithm for a certain amount of Monte /** @brief Execute the Metropolis algorithm for a certain amount of Monte
* Carlo cycles. * Carlo cycles.
@ -64,7 +64,8 @@ void pd_estimate(double T, int L, int cycles,
* *
* @return data_t * @return data_t
* */ * */
data_t mcmc_serial(int L, double T, int cycles, int burn_in_time = BURN_IN_TIME); data_t mcmc_serial(int L, double T, int cycles,
int burn_in_time = BURN_IN_TIME);
/** @brief Execute the Metropolis algorithm for a certain amount of Monte /** @brief Execute the Metropolis algorithm for a certain amount of Monte
* Carlo cycles in parallel. * Carlo cycles in parallel.
@ -75,7 +76,8 @@ data_t mcmc_serial(int L, double T, int cycles, int burn_in_time = BURN_IN_TIME)
* *
* @return data_t * @return data_t
* */ * */
data_t mcmc_parallel(int L, double T, int cycles, int burn_in_time = BURN_IN_TIME); data_t mcmc_parallel(int L, double T, int cycles,
int burn_in_time = BURN_IN_TIME);
/** @brief Perform the MCMC algorithm using a range of temperatures. /** @brief Perform the MCMC algorithm using a range of temperatures.
* *
@ -86,10 +88,10 @@ data_t mcmc_parallel(int L, double T, int cycles, int burn_in_time = BURN_IN_TIM
* @param monte_carlo Which Monte Carlo implementation to use * @param monte_carlo Which Monte Carlo implementation to use
* @param outfile The file to write the data to * @param outfile The file to write the data to
* */ * */
void void phase_transition(int L, double start_T, double end_T, int points_T,
phase_transition(int L, double start_T, double end_T, int points_T, int cycles, int cycles,
std::function<data_t(int, double, int, int)> monte_carlo, std::function<data_t(int, double, int, int)> monte_carlo,
std::string outfile, int burn_in_time = BURN_IN_TIME); std::string outfile, int burn_in_time = BURN_IN_TIME);
}; // namespace montecarlo }; // namespace montecarlo
#endif #endif

View File

@ -114,6 +114,21 @@ bool mkpath(std::string path, int mode = 0777);
* */ * */
std::string dirname(const std::string &path); std::string dirname(const std::string &path);
/** @brief Take 2 strings and concatenate them and make sure there is a
* directory separator (/) between them.
*
* @details This function doesn't care whether or not the values given as
* parameters are valid path strings. It is the responsibility of the user to make
* sure that the values given are valid path strings.
* The function only guarantees that the output string is a valid path string.
*
* @param left The left hand side of the result string
* @param right The right hand side of the result string
*
* @return string
* */
std::string concatpath(const std::string &left, const std::string &right);
} // namespace utils } // namespace utils
#endif #endif

View File

@ -13,6 +13,8 @@
#include "monte_carlo.hpp" #include "monte_carlo.hpp"
#include "utils.hpp" #include "utils.hpp"
#include <getopt.h>
/** @brief Create the data for the burn-in time for temperatures 1.0 and 2.4 /** @brief Create the data for the burn-in time for temperatures 1.0 and 2.4
* for both unordered and ordered initial states. * for both unordered and ordered initial states.
* */ * */
@ -43,10 +45,12 @@ void create_pd_estimate_data()
void test_burn_in_time() void test_burn_in_time()
{ {
montecarlo::phase_transition(100, 2.1, 2.4, 40, 1e5, montecarlo::mcmc_serial, montecarlo::phase_transition(
"../output/test_burn_in_time/no_burn_in.txt", 0); 100, 2.1, 2.4, 40, 1e5, montecarlo::mcmc_serial,
montecarlo::phase_transition(100, 2.1, 2.4, 40, 1e5, montecarlo::mcmc_serial, "../output/test_burn_in_time/no_burn_in.txt", 0);
"../output/test_burn_in_time/burn_in.txt", 5000); montecarlo::phase_transition(
100, 2.1, 2.4, 40, 1e5, montecarlo::mcmc_serial,
"../output/test_burn_in_time/burn_in.txt", 5000);
} }
/** @brief Test how much Openmp speeds up.*/ /** @brief Test how much Openmp speeds up.*/
@ -99,36 +103,70 @@ void create_phase_transition_data()
std::cout << "Time: " << t1 - t0 << std::endl; std::cout << "Time: " << t1 - t0 << std::endl;
} }
void usage(std::string filename)
{
std::cout << "Usage: " << filename << " OPTION ...\n"
<< "At least one option should be used.\n\n"
<< "\t[ -h | --help ]\n"
<< "\t[ --all ]\n"
<< "\t[ --create-burn-in-data ]\n"
<< "\t[ --create-pd-estimate-data ]\n"
<< "\t[ --create-phase-transition-data ]\n"
<< "\t[ --test-parallel-speedup ]\n"
<< "\t[ --test-burn-in-time ]\n";
exit(-1);
}
/** @brief The main function.*/ /** @brief The main function.*/
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
if (argc < 2) { static struct option long_options[] = {
std::cout << "Need at least 1 argument, got " << argc - 1 {"all", no_argument, 0, 0},
<< " arguments." << std::endl; {"create-burn-in-data", no_argument, 0, 0},
abort(); {"create-pd-estimate-data", no_argument, 0, 0},
} {"test-parallel-speedup", no_argument, 0, 0},
{"create-phase-transition-data", no_argument, 0, 0},
{"test-burn-in-time", no_argument, 0, 0},
{"help", no_argument, 0, 0}};
int arg = atoi(argv[1]); int option_index = -1;
int c;
switch (arg) { while (true) {
case 1: c = getopt_long(argc, argv, "h", long_options, &option_index);
create_burn_in_time_data();
break; if (c == -1)
case 2: break;
create_pd_estimate_data(); else if (c == 'h')
break; usage(argv[0]);
case 3:
test_parallel_speedup(); switch (option_index) {
break; case 0:
case 4: create_burn_in_time_data();
create_phase_transition_data(); create_pd_estimate_data();
break; test_parallel_speedup();
case 5: create_phase_transition_data();
test_burn_in_time(); test_burn_in_time();
break; break;
default: case 1:
std::cout << "Not a valid option!" << std::endl; create_burn_in_time_data();
abort(); break;
case 2:
create_pd_estimate_data();
break;
case 3:
test_parallel_speedup();
break;
case 4:
create_phase_transition_data();
break;
case 5:
test_burn_in_time();
break;
case 6: // Not a mistake. This just goes to the default.
default:
usage(argv[0]);
}
} }
return 0; return 0;

79
src/mcmc_progression.cpp Normal file
View File

@ -0,0 +1,79 @@
/** @file mcmc_progression.cpp
*
* @author Cory Alexander Balaton (coryab)
* @author Janita Ovidie Sandtrøen Willumsen (janitaws)
*
* @version 1.0
*
* @brief Execute the mcmc algorithm and write data to file after each
* Monte Carlo cycle.
*
* @bug No known bugs
* */
#include "data_type.hpp"
#include "monte_carlo.hpp"
#include "utils.hpp"
#include <getopt.h>
#include <omp.h>
#include <string>
void usage(std::string filename)
{
std::cout << "Usage: " << filename
<< " <temperature> <lattice size> "
"<cycles> <burn-in-time> <output file>\n\n"
<< "\t[ -h | --help ]\n";
exit(-1);
}
/** @brief The main function
*
* */
int main(int argc, char **argv)
{
// Command options
struct option long_options[] = {{"help", 0, 0, 0}, {NULL, 0, NULL, 0}};
int option_index = -1;
int c;
while (true) {
c = getopt_long(argc, argv, "h", long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 0:
switch (option_index) {
case 0: // Not a mistake. This just goes to the default.
default:
usage(argv[0]);
}
break;
case 'h':
default:
usage(argv[0]);
}
}
// Check that the number of arguments is at least 8.
if (argc < 6) {
usage(argv[0]);
}
// Timing variables
double t0, t1;
t0 = omp_get_wtime();
// Define/initialize variables
double temp = atoi(argv[1]);
int L = atoi(argv[2]), cycles = atoi(argv[3]), burn_in_time = atoi(argv[4]);
std::string outfile = argv[5];
montecarlo::progression(temp, L, cycles, outfile, burn_in_time);
t1 = omp_get_wtime();
std::cout << "Time: " << t1 - t0 << " seconds\n";
}

View File

@ -12,7 +12,8 @@
#include "monte_carlo.hpp" #include "monte_carlo.hpp"
namespace montecarlo { namespace montecarlo {
void progression(double T, int L, int cycles, const std::string filename) void progression(double T, int L, int cycles, const std::string filename,
int burn_in_time)
{ {
// Set some variables // Set some variables
data_t data, tmp; data_t data, tmp;
@ -35,6 +36,10 @@ void progression(double T, int L, int cycles, const std::string filename)
utils::mkpath(directory); utils::mkpath(directory);
ofile.open(filename); ofile.open(filename);
for (size_t i = 0; i < burn_in_time; i++) {
ising.Metropolis();
}
// Loop through cycles // Loop through cycles
for (size_t i = 1; i <= cycles; i++) { for (size_t i = 1; i <= cycles; i++) {
data += ising.Metropolis(); data += ising.Metropolis();
@ -46,7 +51,7 @@ void progression(double T, int L, int cycles, const std::string filename)
} }
void progression(double T, int L, int cycles, int value, void progression(double T, int L, int cycles, int value,
const std::string filename) const std::string filename, int burn_in_time)
{ {
// Set some variables // Set some variables
data_t data, tmp; data_t data, tmp;
@ -65,6 +70,10 @@ void progression(double T, int L, int cycles, int value,
IsingModel ising(L, T, value); IsingModel ising(L, T, value);
for (size_t i = 0; i < burn_in_time; i++) {
ising.Metropolis();
}
// Create path and open file // Create path and open file
utils::mkpath(directory); utils::mkpath(directory);
ofile.open(filename); ofile.open(filename);
@ -79,7 +88,8 @@ void progression(double T, int L, int cycles, int value,
ofile.close(); ofile.close();
} }
void pd_estimate(double T, int L, int cycles, const std::string filename) void pd_estimate(double T, int L, int cycles, const std::string filename,
int burn_in_time)
{ {
// Set some variables // Set some variables
data_t data, tmp; data_t data, tmp;
@ -91,6 +101,10 @@ void pd_estimate(double T, int L, int cycles, const std::string filename)
IsingModel ising(L, T); IsingModel ising(L, T);
for (size_t i = 0; i < burn_in_time; i++) {
ising.Metropolis();
}
// Create path and open file // Create path and open file
utils::mkpath(directory); utils::mkpath(directory);
ofile.open(filename); ofile.open(filename);

79
src/pd_estimate.cpp Normal file
View File

@ -0,0 +1,79 @@
/** @file pd_estimate.cpp
*
* @author Cory Alexander Balaton (coryab)
* @author Janita Ovidie Sandtrøen Willumsen (janitaws)
*
* @version 1.0
*
* @brief execute the mcmc algorithm and write data to file after each
* Monte Carlo cycles.
*
* @bug No known bugs
* */
#include "data_type.hpp"
#include "monte_carlo.hpp"
#include "utils.hpp"
#include <getopt.h>
#include <omp.h>
#include <string>
void usage(std::string filename)
{
std::cout << "Usage: " << filename
<< " <temperature> <lattice size> "
"<cycles> <burn-in-time> <output file>\n\n"
<< "\t[ -h | --help ]\n";
exit(-1);
}
/** @brief The main function
*
* */
int main(int argc, char **argv)
{
// Command options
struct option long_options[] = {{"help", 0, 0, 0}, {NULL, 0, NULL, 0}};
int option_index = -1;
int c;
while (true) {
c = getopt_long(argc, argv, "h", long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 0:
switch (option_index) {
case 0: // Not a mistake. This just goes to the default.
default:
usage(argv[0]);
}
break;
case 'h':
default:
usage(argv[0]);
}
}
// Check that the number of arguments is at least 8.
if (argc < 6) {
usage(argv[0]);
}
// Timing variables
double t0, t1;
t0 = omp_get_wtime();
// Define/initialize variables
double temp = atoi(argv[1]);
int L = atoi(argv[2]), cycles = atoi(argv[3]), burn_in_time = atoi(argv[4]);
std::string outfile = argv[5];
montecarlo::pd_estimate(temp, L, cycles, outfile, burn_in_time);
t1 = omp_get_wtime();
std::cout << "Time: " << t1 - t0 << " seconds\n";
}

84
src/phase_transition.cpp Normal file
View File

@ -0,0 +1,84 @@
/** @file phase_transition.cpp
*
* @author Cory Alexander Balaton (coryab)
* @author Janita Ovidie Sandtrøen Willumsen (janitaws)
*
* @version 1.0
*
* @brief Sweep over different temperatures and generate data.
*
* @details This program takes in 4 arguments: the start temperature,
* the end temperature, the amount of temperature points to simulate, and
* the amount of monte carlo samples to collect, in that order.
*
* @bug No known bugs
* */
#include "data_type.hpp"
#include "monte_carlo.hpp"
#include "utils.hpp"
#include <getopt.h>
#include <omp.h>
#include <string>
void usage(std::string filename)
{
std::cout << "Usage: " << filename
<< " <start temperature> <end temperature> <lattice size> "
"<points> <cycles> <burn-in-time> <output file>\n\n"
<< "\t[ -h | --help ]\n";
exit(-1);
}
/** @brief The main function
*
* */
int main(int argc, char **argv)
{
// Command options
struct option long_options[] = {{"help", 0, 0, 0}, {NULL, 0, NULL, 0}};
int option_index = -1;
int c;
while (true) {
c = getopt_long(argc, argv, "h", long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 0:
switch (option_index) {
case 0: // Not a mistake. This just goes to the default.
default:
usage(argv[0]);
}
break;
case 'h':
default:
usage(argv[0]);
}
}
// Check that the number of arguments is at least 8.
if (argc < 8) {
usage(argv[0]);
}
// Timing variables
double t0, t1;
t0 = omp_get_wtime();
// Define/initialize variables
double start = atof(argv[1]), end = atof(argv[2]);
int points = atoi(argv[3]), cycles = atoi(argv[5]), L = atoi(argv[4]),
burn_in_time = atoi(argv[6]), N = L * L;
std::string outfile = argv[7];
montecarlo::phase_transition(L, start, end, points, cycles,
montecarlo::mcmc_parallel, outfile);
t1 = omp_get_wtime();
std::cout << "Time: " << t1 - t0 << " seconds\n";
}

View File

@ -17,17 +17,55 @@
#include "monte_carlo.hpp" #include "monte_carlo.hpp"
#include "utils.hpp" #include "utils.hpp"
#include <getopt.h>
#include <mpi.h> #include <mpi.h>
#include <string>
void usage(std::string filename)
{
std::cout
<< "Usage: " << filename
<< " <start temperature> <end temperature> <lattice size> "
"<points> <cycles> <burn-in-time> <output file>\n"
<< "This should be used with mpiexec or mpirun for maximum "
"performance\n\n"
<< "\t[ -h | --help ]\n";
exit(-1);
}
/** @brief The main function /** @brief The main function
* *
* */ * */
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
// Check that the number of arguments is at least 4. // Command options
if (argc < 7) { struct option long_options[] = {{"help", 0, 0, 0}, {NULL, 0, NULL, 0}};
std::cout << "You need at least 6 arguments" << std::endl;
abort(); int option_index = -1;
int c;
while (true) {
c = getopt_long(argc, argv, "h", long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 0:
switch (option_index) {
case 0: // Not a mistake. This just goes to the default.
default:
usage(argv[0]);
}
break;
case 'h':
default:
usage(argv[0]);
}
}
// Check that the number of arguments is at least 8.
if (argc < 8) {
usage(argv[0]);
} }
// Timing variables // Timing variables
@ -40,6 +78,7 @@ int main(int argc, char **argv)
burn_in_time = atoi(argv[6]), N = L * L; burn_in_time = atoi(argv[6]), N = L * L;
double dt = (end - start) / points; double dt = (end - start) / points;
std::ofstream ofile; std::ofstream ofile;
std::string outfile = argv[7];
data_t data[points]; data_t data[points];
// MPI specific variables // MPI specific variables
@ -100,10 +139,8 @@ int main(int argc, char **argv)
} }
// Write everything from data to file // Write everything from data to file
std::stringstream outfile; utils::mkpath(utils::dirname(outfile));
outfile << "../output/phase_transition/mpi/size_" << L << ".txt"; ofile.open(outfile);
utils::mkpath(utils::dirname(outfile.str()));
ofile.open(outfile.str());
double temp, CV, X; double temp, CV, X;

View File

@ -13,6 +13,7 @@
#include "monte_carlo.hpp" #include "monte_carlo.hpp"
#include "utils.hpp" #include "utils.hpp"
#include <getopt.h>
#include <omp.h> #include <omp.h>
#include <ostream> #include <ostream>
@ -29,8 +30,7 @@ void time_lattice_sizes()
for (int L : lattice_sizes) { for (int L : lattice_sizes) {
t0 = omp_get_wtime(); t0 = omp_get_wtime();
montecarlo::phase_transition(L, 2.1, 2.4, 40, 100000, montecarlo::phase_transition(L, 2.1, 2.4, 40, 100000,
montecarlo::mcmc_parallel, montecarlo::mcmc_parallel, "/dev/null");
"/dev/null");
t1 = omp_get_wtime(); t1 = omp_get_wtime();
ofile << utils::scientific_format(L) << ',' ofile << utils::scientific_format(L) << ','
<< utils::scientific_format(t1 - t0) << '\n'; << utils::scientific_format(t1 - t0) << '\n';
@ -51,8 +51,7 @@ void time_sample_sizes()
for (int samples : sample_sizes) { for (int samples : sample_sizes) {
t0 = omp_get_wtime(); t0 = omp_get_wtime();
montecarlo::phase_transition(20, 2.1, 2.4, 40, samples, montecarlo::phase_transition(20, 2.1, 2.4, 40, samples,
montecarlo::mcmc_parallel, montecarlo::mcmc_parallel, "/dev/null");
"/dev/null");
t1 = omp_get_wtime(); t1 = omp_get_wtime();
ofile << utils::scientific_format(samples) << ',' ofile << utils::scientific_format(samples) << ','
<< utils::scientific_format(t1 - t0) << '\n'; << utils::scientific_format(t1 - t0) << '\n';
@ -60,9 +59,57 @@ void time_sample_sizes()
ofile.close(); ofile.close();
} }
int main() void usage(std::string filename)
{ {
time_lattice_sizes(); std::cout << "Usage: " << filename << " OPTION ...\n"
time_sample_sizes(); << "At least one option should be used.\n\n"
<< "\t[ -h | --help ]\n"
<< "\t[ --all ]\n"
<< "\t[ --time-lattice-sizes ]\n"
<< "\t[ --time-sample-sizes ]\n";
exit(-1);
}
int main(int argc, char **argv)
{
struct option long_options[] = {{"all", 0, 0, 0},
{"time-lattice-sizes", 0, 0, 0},
{"time-sample-sizes", 0, 0, 0},
{"help", 0, 0, 0},
{NULL, 0, NULL, 0}};
int option_index = -1;
int c;
while (true) {
c = getopt_long(argc, argv, "h", long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 0:
switch (option_index) {
case 0:
time_lattice_sizes();
time_sample_sizes();
break;
case 1:
time_lattice_sizes();
break;
case 2:
time_sample_sizes();
break;
case 3: // Not a mistake. This just goes to the default.
default:
usage(argv[0]);
}
break;
case 'h':
default:
usage(argv[0]);
}
}
return 0; return 0;
} }

View File

@ -60,4 +60,14 @@ std::string dirname(const std::string &path)
return path.substr(0, path.find_last_of("/")); return path.substr(0, path.find_last_of("/"));
} }
std::string concatpath(const std::string &left, const std::string &right)
{
if (left.back() != '/' and right.front() != '/') {
return left + '/' + right;
}
else {
return left + right;
}
}
} // namespace utils } // namespace utils