Make changes
This commit is contained in:
parent
84692040d3
commit
237bd37184
@ -18,6 +18,7 @@
|
||||
#include "utils.hpp"
|
||||
|
||||
#include <armadillo>
|
||||
#include <cstdint>
|
||||
#include <random>
|
||||
#include <unordered_map>
|
||||
|
||||
@ -53,7 +54,8 @@ private:
|
||||
|
||||
/** @brief A hash map containing all possible energy changes.
|
||||
* */
|
||||
std::unordered_map<int, double> energy_diff;
|
||||
//std::unordered_map<int, double> energy_diff;
|
||||
double energy_diff[17];
|
||||
|
||||
/** @brief The temperature of the model.
|
||||
* */
|
||||
@ -65,12 +67,15 @@ private:
|
||||
|
||||
/** @brief The current energy state. unit: \f$ J \f$.
|
||||
* */
|
||||
int E;
|
||||
int64_t E;
|
||||
|
||||
/** @brief The current magnetic strength. unit: Unitless.
|
||||
* */
|
||||
int M;
|
||||
int64_t M;
|
||||
|
||||
std::mt19937 engine;
|
||||
|
||||
void initialize_engine();
|
||||
/** @brief Initialize the lattice with a random distribution of 1s and
|
||||
* -1s.
|
||||
* */
|
||||
|
||||
@ -49,7 +49,7 @@ public:
|
||||
return res;
|
||||
}
|
||||
|
||||
template <class T> data_t& operator/=(T num)
|
||||
template <class T> data_t &operator/=(T num)
|
||||
{
|
||||
this->E /= (double)num;
|
||||
this->E2 /= (double)num;
|
||||
@ -72,7 +72,7 @@ public:
|
||||
return res;
|
||||
}
|
||||
|
||||
template <class T> data_t& operator*=(T num)
|
||||
template <class T> data_t &operator*=(T num)
|
||||
{
|
||||
this->E *= (double)num;
|
||||
this->E2 *= (double)num;
|
||||
@ -95,7 +95,7 @@ public:
|
||||
return res;
|
||||
}
|
||||
|
||||
data_t& operator+=(const data_t &b)
|
||||
data_t &operator+=(const data_t &b)
|
||||
{
|
||||
this->E += b.E;
|
||||
this->E2 += b.E2;
|
||||
@ -116,4 +116,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#pragma omp declare reduction(+ : data_t : omp_out += omp_in)
|
||||
|
||||
#endif
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
*
|
||||
* @version 1.0
|
||||
*
|
||||
* @brief Functions for monte carlo simulations.
|
||||
* @brief Functions for Monte Carlo simulations.
|
||||
*
|
||||
* @bug No known bugs
|
||||
* */
|
||||
@ -17,23 +17,13 @@
|
||||
#include "utils.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <omp.h>
|
||||
#include <string>
|
||||
|
||||
//#define BURN_IN_TIME 12500
|
||||
// #define BURN_IN_TIME 12500
|
||||
#define BURN_IN_TIME 5000
|
||||
|
||||
#pragma omp declare reduction(+: data_t: omp_out += omp_in)
|
||||
|
||||
/** @brief Test numerical data with analytical data.
|
||||
*
|
||||
* @param tol The tolerance between the analytical and numerical solution.
|
||||
* @param max_cycles The max number of Monte Carlo cycles.
|
||||
*
|
||||
* return int
|
||||
* */
|
||||
int test_2x2_lattice(double tol, int max_cycles);
|
||||
|
||||
namespace montecarlo {
|
||||
/** @brief Write the expected values for each Monte Carlo cycles to file.
|
||||
*
|
||||
* @param T Temperature
|
||||
@ -41,7 +31,7 @@ int test_2x2_lattice(double tol, int max_cycles);
|
||||
* @param cycles The amount of Monte Carlo cycles to do
|
||||
* @param filename The file to write to
|
||||
* */
|
||||
void monte_carlo_progression(double T, int L, int cycles,
|
||||
void progression(double T, int L, int cycles,
|
||||
const std::string filename);
|
||||
|
||||
/** @brief Write the expected values for each Monte Carlo cycles to file.
|
||||
@ -52,7 +42,7 @@ void monte_carlo_progression(double T, int L, int cycles,
|
||||
* @param value The value to set the elements in the lattice
|
||||
* @param filename The file to write to
|
||||
* */
|
||||
void monte_carlo_progression(double T, int L, int cycles, int value,
|
||||
void progression(double T, int L, int cycles, int value,
|
||||
const std::string filename);
|
||||
|
||||
/** @brief Estimate the probability distribution for the energy.
|
||||
@ -62,7 +52,8 @@ void monte_carlo_progression(double T, int L, int cycles, int value,
|
||||
* @param cycles The amount of Monte Carlo cycles to do
|
||||
* @param filename The file to write to
|
||||
* */
|
||||
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);
|
||||
|
||||
/** @brief Execute the Metropolis algorithm for a certain amount of Monte
|
||||
* Carlo cycles.
|
||||
@ -73,7 +64,7 @@ void pd_estimate(double T, int L, int cycles, const std::string filename);
|
||||
*
|
||||
* @return data_t
|
||||
* */
|
||||
data_t monte_carlo_serial(int L, double T, int cycles);
|
||||
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
|
||||
* Carlo cycles in parallel.
|
||||
@ -84,7 +75,7 @@ data_t monte_carlo_serial(int L, double T, int cycles);
|
||||
*
|
||||
* @return data_t
|
||||
* */
|
||||
data_t monte_carlo_parallel(int L, double T, int cycles);
|
||||
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.
|
||||
*
|
||||
@ -95,9 +86,10 @@ data_t monte_carlo_parallel(int L, double T, int cycles);
|
||||
* @param monte_carlo Which Monte Carlo implementation to use
|
||||
* @param outfile The file to write the data to
|
||||
* */
|
||||
void phase_transition(
|
||||
int L, double start_T, double end_T, int points_T,
|
||||
std::function<data_t(int, double, int)> monte_carlo,
|
||||
std::string outfile);
|
||||
void
|
||||
phase_transition(int L, double start_T, double end_T, int points_T, int cycles,
|
||||
std::function<data_t(int, double, int, int)> monte_carlo,
|
||||
std::string outfile, int burn_in_time = BURN_IN_TIME);
|
||||
}; // namespace montecarlo
|
||||
|
||||
#endif
|
||||
|
||||
64
slurm_scripts/execute.script
Executable file
64
slurm_scripts/execute.script
Executable file
@ -0,0 +1,64 @@
|
||||
#!/bin/bash
|
||||
|
||||
usage() {
|
||||
>&2 cat << EOF
|
||||
Usage: $0
|
||||
[ -h | --help ]
|
||||
[ --start-temp input ]
|
||||
[ --end-temp input ]
|
||||
[ --points input ]
|
||||
[ --samples input ]
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Defaults
|
||||
start_temp=2.1
|
||||
end_temp=2.4
|
||||
points_temp=40
|
||||
samples=1000000
|
||||
array_arg=20
|
||||
time_arg="0-00:30:00"
|
||||
|
||||
VALID_ARGS=$(getopt -o h --long help,start-temp:,end-temp:,points:,samples:,array:,time: -- "$@")
|
||||
if [[ $? -ne 0 ]]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
eval set -- ${VALID_ARGS}
|
||||
while :
|
||||
do
|
||||
case "$1" in
|
||||
-h | --help)
|
||||
usage
|
||||
shift
|
||||
;;
|
||||
--start-temp)
|
||||
start_temp=$2
|
||||
shift 2
|
||||
;;
|
||||
--end-temp)
|
||||
end_temp=$2
|
||||
shift 2
|
||||
;;
|
||||
--points)
|
||||
points=$2
|
||||
shift 2
|
||||
;;
|
||||
--samples)
|
||||
samples=$2
|
||||
shift 2
|
||||
;;
|
||||
--array)
|
||||
array_arg=$(echo "${2// /}")
|
||||
shift 2
|
||||
;;
|
||||
--time)
|
||||
time_arg=$2
|
||||
shift 2
|
||||
;;
|
||||
--) shift; break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
sbatch --array=$array_arg --time=$time_arg ./jobs/pt.script $start_temp $end_temp $points_temp $samples
|
||||
22
slurm_scripts/pt.script
Executable file
22
slurm_scripts/pt.script
Executable file
@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
#SBATCH --account=ec54
|
||||
#SBATCH --job-name=pt
|
||||
#SBATCH --ntasks=10
|
||||
#SBATCH --mem-per-cpu=1G
|
||||
#SBATCH --cpus-per-task=10
|
||||
|
||||
set -o errexit # Exit the script on any error
|
||||
set -o nounset # Treat any unset variables as an error
|
||||
|
||||
module --quiet purge # Reset the modules to the system default
|
||||
module load Armadillo/11.4.3-foss-2022b
|
||||
module load OpenMPI/4.1.5-GCC-12.3.0
|
||||
|
||||
# Args
|
||||
start_temp=$1
|
||||
end_temp=$2
|
||||
points_temp=$3
|
||||
samples=$4
|
||||
|
||||
srun ./phase_transition_mpi $start_temp $end_temp $points_temp ${SLURM_ARRAY_TASK_ID} $samples 0
|
||||
17
slurm_scripts/pt_narrow.script
Normal file
17
slurm_scripts/pt_narrow.script
Normal file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
#SBATCH --account=ec54
|
||||
#SBATCH --job-name=pt_narrow
|
||||
#SBATCH --time=0-02:00:00
|
||||
#SBATCH --ntasks=8
|
||||
#SBATCH --mem-per-cpu=1G
|
||||
#SBATCH --cpus-per-task=10
|
||||
|
||||
set -o errexit # Exit the script on any error
|
||||
set -o nounset # Treat any unset variables as an error
|
||||
|
||||
module --quiet purge # Reset the modules to the system default
|
||||
module load Armadillo/11.4.3-foss-2022b
|
||||
module load OpenMPI/4.1.5-GCC-12.3.0
|
||||
|
||||
srun ./phase_transition_mpi 2.25 2.35 40 10000000
|
||||
@ -10,18 +10,18 @@
|
||||
* @bug No known bugs
|
||||
* */
|
||||
#include "IsingModel.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <random>
|
||||
|
||||
IsingModel::IsingModel()
|
||||
{
|
||||
this->initialize_engine();
|
||||
}
|
||||
|
||||
IsingModel::IsingModel(int L, double T)
|
||||
{
|
||||
this->L = L;
|
||||
this->T = T;
|
||||
this->initialize_engine();
|
||||
this->initialize_lattice();
|
||||
this->initialize_neighbors();
|
||||
this->initialize_energy_diff();
|
||||
@ -33,6 +33,7 @@ IsingModel::IsingModel(int L, double T, int val)
|
||||
{
|
||||
this->L = L;
|
||||
this->T = T;
|
||||
this->initialize_engine();
|
||||
this->lattice.set_size(this->L, this->L);
|
||||
this->lattice.fill(val);
|
||||
this->initialize_neighbors();
|
||||
@ -41,16 +42,20 @@ IsingModel::IsingModel(int L, double T, int val)
|
||||
this->initialize_energy();
|
||||
}
|
||||
|
||||
void IsingModel::initialize_engine()
|
||||
{
|
||||
std::random_device rd{};
|
||||
this->engine = std::mt19937{rd()};
|
||||
}
|
||||
|
||||
void IsingModel::initialize_lattice()
|
||||
{
|
||||
this->lattice.set_size(this->L, this->L);
|
||||
std::random_device rd{};
|
||||
std::mt19937 engine{rd()};
|
||||
|
||||
std::uniform_int_distribution<> coin_flip(0, 1);
|
||||
|
||||
for (size_t i = 0; i < this->lattice.n_elem; i++)
|
||||
this->lattice(i) = 2 * coin_flip(engine) - 1;
|
||||
this->lattice(i) = 2 * coin_flip(this->engine) - 1;
|
||||
}
|
||||
|
||||
void IsingModel::initialize_neighbors()
|
||||
@ -67,7 +72,7 @@ void IsingModel::initialize_neighbors()
|
||||
void IsingModel::initialize_energy_diff()
|
||||
{
|
||||
for (int i = -8; i <= 8; i += 4) {
|
||||
this->energy_diff.insert({i, std::exp(-(double)i / this->T)});
|
||||
this->energy_diff[i+8] = std::exp(-(double)i / this->T);
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,9 +100,6 @@ void IsingModel::initialize_energy()
|
||||
|
||||
data_t IsingModel::Metropolis()
|
||||
{
|
||||
std::random_device rd{};
|
||||
std::mt19937_64 engine{rd()};
|
||||
|
||||
int ri, rj;
|
||||
int dE;
|
||||
|
||||
@ -120,7 +122,7 @@ data_t IsingModel::Metropolis()
|
||||
+ this->lattice(this->neighbors(ri, DOWN), rj));
|
||||
|
||||
// Choose whether or not to accept the new configuration
|
||||
if (random_number(engine) <= this->energy_diff[dE]) {
|
||||
if (random_number(engine) <= this->energy_diff[dE+8]) {
|
||||
// Update if the configuration is accepted
|
||||
this->lattice(ri, rj) *= -1;
|
||||
this->M += 2 * this->lattice(ri, rj);
|
||||
|
||||
23
src/Makefile
23
src/Makefile
@ -3,9 +3,11 @@ CC=mpic++
|
||||
|
||||
LIBSRCS=utils.cpp testlib.cpp data_type.cpp
|
||||
LIBOBJS=$(LIBSRCS:.cpp=.o)
|
||||
LIBPROFOBJS=$(addprefix prof/, $(LIBOBJS))
|
||||
|
||||
CLASSSRCS=IsingModel.cpp monte_carlo.cpp
|
||||
CLASSOBJS=$(CLASSSRCS:.cpp=.o)
|
||||
CLASSPROFOBJS=$(addprefix prof/, $(CLASSOBJS))
|
||||
|
||||
INCLUDE=../include
|
||||
|
||||
@ -29,16 +31,14 @@ else
|
||||
PROFFLAG=
|
||||
endif
|
||||
|
||||
.PHONY: clean
|
||||
.PHONY: clean instrument
|
||||
|
||||
all: main phase_transition_mpi test_suite
|
||||
all: main phase_transition_mpi test_suite time
|
||||
#all: main
|
||||
|
||||
# Instrumentation using scorep for parallel analysis
|
||||
instrument:
|
||||
scorep $(CC) -c utils.cpp -o utils.o $(CFLAGS) $(DBGFLAG) $(PROFFLAG) -I$(INCLUDE) $(OPENMP)
|
||||
scorep $(CC) -c main.cpp -o main.o $(CFLAGS) $(DBGFLAG) $(PROFFLAG) -I$(INCLUDE) $(OPENMP)
|
||||
scorep $(CC) $(LIBOBJS) $(CLASSOBJS) main.o -o main $(CFLAGS) $(DBGFLAG) $(PROFFLAG) -I$(INCLUDE) $(OPENMP)
|
||||
instrument: prof/phase_transition_mpi.o $(LIBPROFOBJS) $(CLASSPROFOBJS)
|
||||
scorep $(CC) $(LIBPROFOBJS) $(CLASSPROFOBJS) $< -o phase_transition_mpi_prof $(CFLAGS) $(DBGFLAG) $(PROFFLAG) -I$(INCLUDE) $(OPENMP)
|
||||
|
||||
# Rules for executables
|
||||
main: main.o $(LIBOBJS) $(CLASSOBJS)
|
||||
@ -50,10 +50,17 @@ phase_transition_mpi: phase_transition_mpi.o $(LIBOBJS) $(CLASSOBJS)
|
||||
test_suite: test_suite.o $(LIBOBJS) $(CLASSOBJS)
|
||||
$(CC) $^ -o $@ $(CFLAGS) $(DBGFLAG) $(PROFFLAG) -I$(INCLUDE) $(OPENMP)
|
||||
|
||||
time: time.o $(LIBOBJS) $(CLASSOBJS)
|
||||
$(CC) $^ -o $@ $(CFLAGS) $(DBGFLAG) $(PROFFLAG) -I$(INCLUDE) $(OPENMP)
|
||||
|
||||
# Rule for object files
|
||||
%.o: %.cpp
|
||||
$(CC) -c $^ -o $@ $(CFLAGS) $(DBGFLAG) $(PROFFLAG) -I$(INCLUDE) $(OPENMP)
|
||||
|
||||
# Rule for instrumented object files
|
||||
prof/%.o: %.cpp
|
||||
scorep $(CC) -c $^ -o $@ $(CFLAGS) $(DBGFLAG) $(PROFFLAG) -I$(INCLUDE) $(OPENMP)
|
||||
|
||||
clean:
|
||||
rm *.o
|
||||
rm test_suite main
|
||||
find . -maxdepth 2 -name "*.o" -type f -delete
|
||||
rm test_suite main phase_transition_mpi phase_transition_mpi_prof time
|
||||
|
||||
76
src/main.cpp
76
src/main.cpp
@ -13,31 +13,43 @@
|
||||
#include "monte_carlo.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
#include <csignal>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <omp.h>
|
||||
|
||||
/** @brief Create the data for the burn-in time for temperatures 1.0 and 2.4
|
||||
* for both unordered and ordered initial states.
|
||||
* */
|
||||
void create_burn_in_time_data()
|
||||
{
|
||||
// Test burn-in time
|
||||
monte_carlo_progression(1.0, 20, 20000,
|
||||
"output/burn_in_time/unordered_1_0.txt");
|
||||
monte_carlo_progression(1.0, 20, 20000, 1,
|
||||
"output/burn_in_time/ordered_1_0.txt");
|
||||
monte_carlo_progression(2.4, 20, 20000,
|
||||
"output/burn_in_time/unordered_2_4.txt");
|
||||
monte_carlo_progression(2.4, 20, 20000, 1,
|
||||
"output/burn_in_time/ordered_2_4.txt");
|
||||
montecarlo::progression(1.0, 20, 20000,
|
||||
"../output/burn_in_time/unordered_1_0.txt");
|
||||
montecarlo::progression(1.0, 20, 20000, 1,
|
||||
"../output/burn_in_time/ordered_1_0.txt");
|
||||
montecarlo::progression(2.4, 20, 20000,
|
||||
"../output/burn_in_time/unordered_2_4.txt");
|
||||
montecarlo::progression(2.4, 20, 20000, 1,
|
||||
"../output/burn_in_time/ordered_2_4.txt");
|
||||
}
|
||||
|
||||
/** @brief Create the data used to estimate the probability distribution
|
||||
* for tempratures 1.0 anbd 2.4.
|
||||
* */
|
||||
void create_pd_estimate_data()
|
||||
{
|
||||
// Estimate pd
|
||||
pd_estimate(1.0, 20, 1000000, "output/pd_estimate/estimate_1_0.txt");
|
||||
pd_estimate(2.4, 20, 1000000, "output/pd_estimate/estimate_2_4.txt");
|
||||
montecarlo::pd_estimate(1.0, 20, 1000000,
|
||||
"../output/pd_estimate/estimate_1_0.txt");
|
||||
montecarlo::pd_estimate(2.4, 20, 1000000,
|
||||
"../output/pd_estimate/estimate_2_4.txt");
|
||||
}
|
||||
|
||||
void test_burn_in_time()
|
||||
{
|
||||
montecarlo::phase_transition(100, 2.1, 2.4, 40, 1e5, montecarlo::mcmc_serial,
|
||||
"../output/test_burn_in_time/no_burn_in.txt", 0);
|
||||
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.*/
|
||||
void test_parallel_speedup()
|
||||
{
|
||||
// Test the openmp speedup
|
||||
@ -46,10 +58,10 @@ void test_parallel_speedup()
|
||||
int tries = 5;
|
||||
t0 = omp_get_wtime();
|
||||
for (size_t i = 0; i < tries; i++)
|
||||
monte_carlo_serial(20, 1.0, 10000);
|
||||
montecarlo::mcmc_serial(20, 1.0, 10000);
|
||||
t1 = omp_get_wtime();
|
||||
for (size_t i = 0; i < tries; i++)
|
||||
monte_carlo_parallel(20, 1.0, 10000);
|
||||
montecarlo::mcmc_parallel(20, 1.0, 10000);
|
||||
t2 = omp_get_wtime();
|
||||
|
||||
std::cout << "Time serial : " << (t1 - t0) / tries << " seconds"
|
||||
@ -59,22 +71,29 @@ void test_parallel_speedup()
|
||||
std::cout << "Speedup parallel: " << (t1 - t0) / (t2 - t1) << '\n';
|
||||
}
|
||||
|
||||
/** @brief Create data for studying phase transition.
|
||||
* */
|
||||
void create_phase_transition_data()
|
||||
{
|
||||
double t0, t1;
|
||||
|
||||
t0 = omp_get_wtime();
|
||||
// Phase transition
|
||||
phase_transition(20, 2.1, 2.4, 40, monte_carlo_parallel,
|
||||
"output/phase_transition/size_20.txt");
|
||||
phase_transition(40, 2.1, 2.4, 40, monte_carlo_parallel,
|
||||
"output/phase_transition/size_40.txt");
|
||||
phase_transition(60, 2.1, 2.4, 40, monte_carlo_parallel,
|
||||
"output/phase_transition/size_60.txt");
|
||||
phase_transition(80, 2.1, 2.4, 40, monte_carlo_parallel,
|
||||
"output/phase_transition/size_80.txt");
|
||||
phase_transition(100, 2.1, 2.4, 40, monte_carlo_parallel,
|
||||
"output/phase_transition/size_100.txt");
|
||||
montecarlo::phase_transition(20, 2.1, 2.4, 40, 1e4,
|
||||
montecarlo::mcmc_parallel,
|
||||
"../output/phase_transition/size_20.txt");
|
||||
montecarlo::phase_transition(40, 2.1, 2.4, 40, 1e4,
|
||||
montecarlo::mcmc_parallel,
|
||||
"../output/phase_transition/size_40.txt");
|
||||
montecarlo::phase_transition(60, 2.1, 2.4, 40, 1e4,
|
||||
montecarlo::mcmc_parallel,
|
||||
"../output/phase_transition/size_60.txt");
|
||||
montecarlo::phase_transition(80, 2.1, 2.4, 40, 1e4,
|
||||
montecarlo::mcmc_parallel,
|
||||
"../output/phase_transition/size_80.txt");
|
||||
montecarlo::phase_transition(100, 2.1, 2.4, 40, 1e4,
|
||||
montecarlo::mcmc_parallel,
|
||||
"../output/phase_transition/size_100.txt");
|
||||
t1 = omp_get_wtime();
|
||||
|
||||
std::cout << "Time: " << t1 - t0 << std::endl;
|
||||
@ -104,6 +123,9 @@ int main(int argc, char **argv)
|
||||
case 4:
|
||||
create_phase_transition_data();
|
||||
break;
|
||||
case 5:
|
||||
test_burn_in_time();
|
||||
break;
|
||||
default:
|
||||
std::cout << "Not a valid option!" << std::endl;
|
||||
abort();
|
||||
|
||||
@ -11,11 +11,8 @@
|
||||
* */
|
||||
#include "monte_carlo.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
|
||||
void monte_carlo_progression(double T, int L, int cycles,
|
||||
const std::string filename)
|
||||
namespace montecarlo {
|
||||
void progression(double T, int L, int cycles, const std::string filename)
|
||||
{
|
||||
// Set some variables
|
||||
data_t data, tmp;
|
||||
@ -48,7 +45,7 @@ void monte_carlo_progression(double T, int L, int cycles,
|
||||
ofile.close();
|
||||
}
|
||||
|
||||
void monte_carlo_progression(double T, int L, int cycles, int value,
|
||||
void progression(double T, int L, int cycles, int value,
|
||||
const std::string filename)
|
||||
{
|
||||
// Set some variables
|
||||
@ -108,7 +105,7 @@ void pd_estimate(double T, int L, int cycles, const std::string filename)
|
||||
}
|
||||
|
||||
// Code for seeing phase transitions.
|
||||
data_t monte_carlo_serial(int L, double T, int cycles)
|
||||
data_t mcmc_serial(int L, double T, int cycles, int burn_in_time)
|
||||
{
|
||||
data_t data;
|
||||
IsingModel model(L, T);
|
||||
@ -122,10 +119,12 @@ data_t monte_carlo_serial(int L, double T, int cycles)
|
||||
data += model.Metropolis();
|
||||
}
|
||||
|
||||
return data;
|
||||
double norm = 1. / (double)cycles;
|
||||
|
||||
return data * norm;
|
||||
}
|
||||
|
||||
data_t monte_carlo_parallel(int L, double T, int cycles)
|
||||
data_t mcmc_parallel(int L, double T, int cycles, int burn_in_time)
|
||||
{
|
||||
data_t data;
|
||||
#pragma omp parallel
|
||||
@ -153,12 +152,11 @@ data_t monte_carlo_parallel(int L, double T, int cycles)
|
||||
return data * norm;
|
||||
}
|
||||
|
||||
void phase_transition(int L, double start, double end, int points,
|
||||
std::function<data_t(int, double, int)> monte_carlo,
|
||||
std::string outfile)
|
||||
void phase_transition(int L, double start, double end, int points, int cycles,
|
||||
std::function<data_t(int, double, int, int)> monte_carlo,
|
||||
std::string outfile, int burn_in_time)
|
||||
{
|
||||
double dt = (end - start) / (double)points;
|
||||
int cycles = 10000;
|
||||
int N = L * L;
|
||||
std::ofstream ofile;
|
||||
|
||||
@ -172,7 +170,7 @@ void phase_transition(int L, double start, double end, int points,
|
||||
using utils::scientific_format;
|
||||
for (size_t i = 0; i < points; i++) {
|
||||
temp = start + dt * i;
|
||||
data = monte_carlo(L, temp, cycles);
|
||||
data = monte_carlo(L, temp, cycles, burn_in_time);
|
||||
E_var = (data.E2 - data.E * data.E) / (double)N;
|
||||
M_var = (data.M2 - data.M_abs * data.M_abs) / (double)N;
|
||||
|
||||
@ -184,3 +182,4 @@ void phase_transition(int L, double start, double end, int points,
|
||||
}
|
||||
ofile.close();
|
||||
}
|
||||
} // namespace montecarlo
|
||||
|
||||
@ -7,38 +7,42 @@
|
||||
*
|
||||
* @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 <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <mpi.h>
|
||||
#include <sstream>
|
||||
|
||||
/** @brief The main function*/
|
||||
/** @brief The main function
|
||||
*
|
||||
* */
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 5) {
|
||||
std::cout << "You need at least 4 arguments" << std::endl;
|
||||
// Check that the number of arguments is at least 4.
|
||||
if (argc < 7) {
|
||||
std::cout << "You need at least 6 arguments" << std::endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
// Timing variables
|
||||
double t0, t1;
|
||||
t0 = MPI_Wtime();
|
||||
double start = atof(argv[1]), end = atof(argv[2]);
|
||||
int points = atoi(argv[3]), N;
|
||||
int lattice_sizes[] = {20, 40, 60, 80, 100};
|
||||
double dt = (end - start) / points;
|
||||
int cycles = atoi(argv[4]);
|
||||
std::ofstream ofile;
|
||||
|
||||
// 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;
|
||||
double dt = (end - start) / points;
|
||||
std::ofstream ofile;
|
||||
data_t data[points];
|
||||
|
||||
// MPI stuff
|
||||
// MPI specific variables
|
||||
int rank, cluster_size;
|
||||
|
||||
// Initialize MPI
|
||||
@ -49,8 +53,9 @@ int main(int argc, char **argv)
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
|
||||
|
||||
int remainder = points % cluster_size;
|
||||
double i_start;
|
||||
int i_points;
|
||||
double i_start; // What temperature to start from
|
||||
int i_points; // How many points to simulate
|
||||
|
||||
// Distribute temperature points
|
||||
if (rank < remainder) {
|
||||
i_points = points / cluster_size + 1;
|
||||
@ -61,36 +66,42 @@ int main(int argc, char **argv)
|
||||
i_start = start + dt * (i_points * rank + remainder);
|
||||
}
|
||||
|
||||
// Initialize array to contains data for each temperature point
|
||||
data_t i_data[i_points];
|
||||
std::cout << "Rank " << rank << ": " << i_points << ',' << i_start << '\n';
|
||||
|
||||
for (int L : lattice_sizes) {
|
||||
N = L * L;
|
||||
// Simulate and save data to array
|
||||
for (size_t i = 0; i < i_points; i++) {
|
||||
i_data[i] = monte_carlo_parallel(L, i_start + dt * i, cycles);
|
||||
i_data[i] = montecarlo::mcmc_parallel(L, i_start + dt * i, cycles,
|
||||
burn_in_time);
|
||||
}
|
||||
|
||||
// Rank 0 collects all the data and copies it to the "master"
|
||||
// data array.
|
||||
if (rank == 0) {
|
||||
// Copy its own i_data to the data array
|
||||
std::copy_n(i_data, i_points, data);
|
||||
|
||||
// Collect i_data from other ranks in order and copy to data.
|
||||
for (size_t i = 1; i < cluster_size; i++) {
|
||||
if (rank < remainder) {
|
||||
MPI_Recv((void *)i_data,
|
||||
sizeof(data_t) * (points / cluster_size + 1),
|
||||
MPI_CHAR, i, MPI_ANY_TAG, MPI_COMM_WORLD,
|
||||
MPI_STATUS_IGNORE);
|
||||
sizeof(data_t) * (points / cluster_size + 1), MPI_CHAR,
|
||||
i, MPI_ANY_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
|
||||
std::copy_n(i_data, points / cluster_size + 1,
|
||||
data + (points / cluster_size) * i);
|
||||
}
|
||||
else {
|
||||
MPI_Recv((void *)i_data,
|
||||
sizeof(data_t) * (points / cluster_size), MPI_CHAR,
|
||||
i, MPI_ANY_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
|
||||
sizeof(data_t) * (points / cluster_size), MPI_CHAR, i,
|
||||
MPI_ANY_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
|
||||
std::copy_n(i_data, points / cluster_size,
|
||||
data + (points / cluster_size) * i + remainder);
|
||||
}
|
||||
}
|
||||
|
||||
// Write everything from data to file
|
||||
std::stringstream outfile;
|
||||
outfile << "output/phase_transition/size_" << L << ".txt";
|
||||
outfile << "../output/phase_transition/mpi/size_" << L << ".txt";
|
||||
utils::mkpath(utils::dirname(outfile.str()));
|
||||
ofile.open(outfile.str());
|
||||
|
||||
@ -112,11 +123,11 @@ int main(int argc, char **argv)
|
||||
}
|
||||
ofile.close();
|
||||
}
|
||||
// For all other ranks, send the data to rank 0
|
||||
else {
|
||||
MPI_Send(i_data, i_points * sizeof(data_t), MPI_CHAR, 0, rank,
|
||||
MPI_COMM_WORLD);
|
||||
}
|
||||
}
|
||||
|
||||
t1 = MPI_Wtime();
|
||||
|
||||
|
||||
@ -12,8 +12,6 @@
|
||||
#include "IsingModel.hpp"
|
||||
#include "testlib.hpp"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#define EPS_2 (-2 * std::sinh(8.)) / (std::cosh(8.) + 3)
|
||||
|
||||
#define MAG_2 (std::exp(8.) + 1) / (2 * (cosh(8.) + 3))
|
||||
@ -29,7 +27,7 @@
|
||||
* */
|
||||
class IsingModelTest {
|
||||
public:
|
||||
/** @brief Test That initializing works as intended.
|
||||
/** @brief Test that initializing works as intended.
|
||||
* */
|
||||
void test_init_functions()
|
||||
{
|
||||
@ -84,15 +82,9 @@ public:
|
||||
int arr[]{0, 0, 0, 0};
|
||||
|
||||
// Loop through cycles
|
||||
//std::ofstream ofile;
|
||||
//ofile.open("output/test_2x2.txt");
|
||||
while (cycles++ < max_cycles) {
|
||||
data += test.Metropolis();
|
||||
tmp = data / cycles;
|
||||
//ofile << cycles << ',' << tmp.E / n_spins << ','
|
||||
//<< tmp.M_abs / n_spins << ','
|
||||
//<< (tmp.E2 - tmp.E * tmp.E) / (T * T) / n_spins << ','
|
||||
//<< (tmp.M2 - tmp.M_abs * tmp.M_abs) / T / n_spins << '\n';
|
||||
if (testlib::close_to(EPS_2, tmp.E / n_spins, tol)
|
||||
&& testlib::close_to(MAG_2, tmp.M_abs / n_spins, tol)
|
||||
&& testlib::close_to(CV_2, (tmp.E2 - tmp.E * tmp.E) / (T * T)
|
||||
@ -102,44 +94,6 @@ public:
|
||||
return cycles;
|
||||
}
|
||||
}
|
||||
//std::cout << EPS_2 << ',' << MAG_2 << ',' << CV_2 << ',' << X_2
|
||||
//<< std::endl;
|
||||
//ofile.close();
|
||||
// cycles = 0;
|
||||
// data = 0;
|
||||
// IsingModel test_mag(L, T);
|
||||
// while (cycles++ < max_cycles) {
|
||||
// data += test.Metropolis();
|
||||
// tmp = data / (cycles * n_spins);
|
||||
// if (testlib::close_to(MAG_2, tmp.M, tol)) {
|
||||
// arr[1] = cycles;
|
||||
// break;
|
||||
//}
|
||||
//}
|
||||
// cycles = 0;
|
||||
// data = 0;
|
||||
// IsingModel test_CV(L, T);
|
||||
// while (cycles++ < max_cycles) {
|
||||
// data += test.Metropolis();
|
||||
// tmp = data / (cycles * n_spins);
|
||||
// if (testlib::close_to(CV_2, (tmp.E2 - tmp.E * tmp.E) / (T * T),
|
||||
// tol)) {
|
||||
// arr[2] = cycles;
|
||||
// break;
|
||||
//}
|
||||
//}
|
||||
// cycles = 0;
|
||||
// data = 0;
|
||||
// IsingModel test_X(L, T);
|
||||
// while (cycles++ < max_cycles) {
|
||||
// data += test.Metropolis();
|
||||
// tmp = data / (cycles * n_spins);
|
||||
// if (testlib::close_to(X_2, (tmp.M2 - tmp.M_abs * tmp.M_abs) / T,
|
||||
// tol)) {
|
||||
// arr[3] = cycles;
|
||||
// break;
|
||||
//}
|
||||
//}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
@ -150,18 +104,23 @@ int main()
|
||||
IsingModelTest test;
|
||||
|
||||
test.test_init_functions();
|
||||
|
||||
int res = 0;
|
||||
int tmp;
|
||||
for (size_t i=0; i < 1000; i++) {
|
||||
int iterations = 10000;
|
||||
int accepted_values = 0;
|
||||
|
||||
// Run through the test multiple times to get a better estimate.
|
||||
for (size_t i=0; i < iterations; i++) {
|
||||
tmp = test.test_2x2_lattice(1e-2, 1e5);
|
||||
if (tmp == 0) {
|
||||
std::cout << "not enough cycles\n";
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
accepted_values++;
|
||||
res += tmp;
|
||||
}
|
||||
|
||||
std::cout << "Res: " << res / 1000 << std::endl;
|
||||
std::cout << "Res: " << res / accepted_values << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
68
src/time.cpp
Normal file
68
src/time.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
/** @file time.cpp
|
||||
*
|
||||
* @author Cory Alexander Balaton (coryab)
|
||||
* @author Janita Ovidie Sandtrøen Willumsen (janitaws)
|
||||
*
|
||||
* @version 0.1
|
||||
*
|
||||
* @brief Timing various things
|
||||
*
|
||||
* @bug No known bugs
|
||||
* */
|
||||
#include "data_type.hpp"
|
||||
#include "monte_carlo.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
#include <omp.h>
|
||||
#include <ostream>
|
||||
|
||||
void time_lattice_sizes()
|
||||
{
|
||||
std::string outfile = "output/timing/lattice_sizes.txt";
|
||||
std::ofstream ofile;
|
||||
|
||||
int lattice_sizes[] = {20, 40, 60, 80, 100};
|
||||
|
||||
utils::mkpath(utils::dirname(outfile));
|
||||
ofile.open(outfile);
|
||||
double t0, t1;
|
||||
for (int L : lattice_sizes) {
|
||||
t0 = omp_get_wtime();
|
||||
montecarlo::phase_transition(L, 2.1, 2.4, 40, 100000,
|
||||
montecarlo::mcmc_parallel,
|
||||
"output/garbage/null.txt");
|
||||
t1 = omp_get_wtime();
|
||||
ofile << utils::scientific_format(L) << ','
|
||||
<< utils::scientific_format(t1 - t0) << '\n';
|
||||
}
|
||||
ofile.close();
|
||||
}
|
||||
|
||||
void time_sample_sizes()
|
||||
{
|
||||
std::string outfile = "output/timing/sample_sizes.txt";
|
||||
std::ofstream ofile;
|
||||
|
||||
int sample_sizes[] = {1000, 10000, 100000};
|
||||
|
||||
utils::mkpath(utils::dirname(outfile));
|
||||
ofile.open(outfile);
|
||||
double t0, t1;
|
||||
for (int samples : sample_sizes) {
|
||||
t0 = omp_get_wtime();
|
||||
montecarlo::phase_transition(20, 2.1, 2.4, 40, samples,
|
||||
montecarlo::mcmc_parallel,
|
||||
"output/garbage/null.txt");
|
||||
t1 = omp_get_wtime();
|
||||
ofile << utils::scientific_format(samples) << ','
|
||||
<< utils::scientific_format(t1 - t0) << '\n';
|
||||
}
|
||||
ofile.close();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
time_lattice_sizes();
|
||||
time_sample_sizes();
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user