168 lines
5.1 KiB
C++
168 lines
5.1 KiB
C++
/** @file test_suite.cpp
|
|
*
|
|
* @author Cory Alexander Balaton (coryab)
|
|
* @author Janita Ovidie Sandtrøen Willumsen (janitaws)
|
|
*
|
|
* @version 1.0
|
|
*
|
|
* @brief Sweep over different temperatures and generate data.
|
|
*
|
|
* @bug No known bugs
|
|
* */
|
|
#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))
|
|
|
|
#define CV_2 \
|
|
16 * (3 * std::cosh(8.) + 1) / ((std::cosh(8.) + 3) * (std::cosh(8.) + 3))
|
|
|
|
#define X_2 \
|
|
(3 * std::exp(8.) + std::exp(-8.) + 3) \
|
|
/ ((std::cosh(8.) + 3) * (std::cosh(8.) + 3))
|
|
|
|
/** @brief Test class for the Ising model
|
|
* */
|
|
class IsingModelTest {
|
|
public:
|
|
/** @brief Test That initializing works as intended.
|
|
* */
|
|
void test_init_functions()
|
|
{
|
|
IsingModel test;
|
|
test.L = 3;
|
|
test.T = 1.;
|
|
|
|
// Test that initializing the lattice only yields 1s and -1s.
|
|
test.initialize_lattice();
|
|
std::function<bool(int)> f = [](int x) { return x == 1 || x == -1; };
|
|
ASSERT(testlib::assert_each(f, test.lattice),
|
|
"Test lattice initialization.");
|
|
|
|
test.initialize_neighbors();
|
|
arma::Mat<int> neighbor_matrix("2, 1 ; 0, 2 ; 1, 0");
|
|
ASSERT(testlib::is_equal(neighbor_matrix, test.neighbors),
|
|
"Test neighbor matrix.");
|
|
|
|
// Fill the lattice with 1s to be able to test the next functions.
|
|
test.lattice.fill(1);
|
|
|
|
// Test the initial magnetization.
|
|
test.initialize_magnetization();
|
|
ASSERT(std::fabs(test.M - 9.) < 1e-8, "Test intial magnetization");
|
|
|
|
// Test that the initial energy is correct
|
|
test.initialize_energy();
|
|
ASSERT(std::fabs(test.E - (-18)) < 1e-8, "Test initial energy.");
|
|
}
|
|
|
|
/** @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)
|
|
{
|
|
data_t data, tmp;
|
|
size_t L = 2;
|
|
size_t n_spins = L * L;
|
|
double T = 1.;
|
|
size_t cycles = 0;
|
|
|
|
// Create random engine using the mersenne twister
|
|
std::random_device rd;
|
|
std::mt19937 engine(rd());
|
|
|
|
IsingModel test(L, T);
|
|
|
|
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)
|
|
/ n_spins, tol)
|
|
&& testlib::close_to(X_2, (tmp.M2 - tmp.M_abs * tmp.M_abs) / T
|
|
/ n_spins, tol)) {
|
|
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;
|
|
}
|
|
};
|
|
|
|
/** @brief The main function.*/
|
|
int main()
|
|
{
|
|
IsingModelTest test;
|
|
|
|
test.test_init_functions();
|
|
int res = 0;
|
|
int tmp;
|
|
for (size_t i=0; i < 1000; i++) {
|
|
tmp = test.test_2x2_lattice(1e-2, 1e5);
|
|
if (tmp == 0) {
|
|
std::cout << "not enough cycles\n";
|
|
break;
|
|
}
|
|
res += tmp;
|
|
}
|
|
|
|
std::cout << "Res: " << res / 1000 << std::endl;
|
|
|
|
return 0;
|
|
}
|