diff --git a/CMakeLists.txt b/CMakeLists.txt index 521b46cfc..e0a98b1e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -265,6 +265,14 @@ if (NOT gsl-lite_FOUND) target_compile_definitions(gsl-lite-v1 INTERFACE gsl_CONFIG_ALLOWS_NONSTRICT_SPAN_COMPARISON=1) endif() +#=============================================================================== +# Catch2 library +#=============================================================================== +find_package_write_status(Catch2) +if (NOT Catch2) + add_subdirectory(vendor/Catch2) +endif() + #=============================================================================== # RPATH information #=============================================================================== @@ -482,6 +490,10 @@ if (OPENMC_USE_MPI) target_link_libraries(libopenmc MPI::MPI_CXX) endif() +# Add cpp tests directory +include(CTest) +add_subdirectory(tests/cpp_unit_tests) + #=============================================================================== # openmc executable #=============================================================================== diff --git a/tests/cpp_unit_tests/CMakeLists.txt b/tests/cpp_unit_tests/CMakeLists.txt new file mode 100644 index 000000000..c26547f77 --- /dev/null +++ b/tests/cpp_unit_tests/CMakeLists.txt @@ -0,0 +1,9 @@ +set(TEST_NAMES + test_distribution +) + +foreach(test ${TEST_NAMES}) + add_executable(${test} ${test}.cpp) + target_link_libraries(${test} Catch2::Catch2WithMain libopenmc) + add_test(NAME ${test} COMMAND ${test} WORKING_DIRECTORY ${UNIT_TEST_BIN_OUTPUT_DIR}) +endforeach() diff --git a/tests/cpp_unit_tests/test_distribution.cpp b/tests/cpp_unit_tests/test_distribution.cpp new file mode 100644 index 000000000..772fc136a --- /dev/null +++ b/tests/cpp_unit_tests/test_distribution.cpp @@ -0,0 +1,40 @@ +#include "openmc/distribution.h" +#include "openmc/random_lcg.h" +#include + +TEST_CASE("Test alias method sampling of a discrete distribution") +{ + int n_samples = 1e6; + double x[5] = {-1.6, 1.1, 20.3, 4.7, 0.9}; + double p[5] = {0.2, 0.1, 0.5, 0.05, 0.15}; + double samples[n_samples]; + + // Initialize distribution + openmc::Discrete dist(x, p, 5); + uint64_t seed = openmc::init_seed(0, 0); + + // Calculate expected distribution mean + double mean = 0.0; + for (size_t i = 0; i < 5; i++) { + mean += x[i] * p[i]; + } + + // Sample distribution and calculate mean + double dist_mean = 0.0; + for (size_t i = 0; i < n_samples; i++) { + samples[i] = dist.sample(&seed); + dist_mean += samples[i]; + } + dist_mean /= n_samples; + + // Calculate standard deviation + double std = 0.0; + for (size_t i = 0; i < n_samples; i++) { + std += (samples[i] - dist_mean) * (samples[i] - dist_mean); + } + std /= n_samples; + + // Require sampled distribution mean is within 3 standard deviations of the + // expected mean + REQUIRE(std::abs(dist_mean - mean) < 3 * std); +}