diff --git a/unittest/c-library/CMakeLists.txt b/unittest/c-library/CMakeLists.txt index b01cd64677..ee7f323c0f 100644 --- a/unittest/c-library/CMakeLists.txt +++ b/unittest/c-library/CMakeLists.txt @@ -17,6 +17,12 @@ target_compile_definitions(test_library_properties PRIVATE -DTEST_INPUT_FOLDER=$ add_test(LibraryProperties test_library_properties) set_tests_properties(LibraryProperties PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") +add_executable(test_library_scatter_gather test_library_scatter_gather.cpp test_main.cpp) +target_link_libraries(test_library_scatter_gather PRIVATE lammps GTest::GTest GTest::GMock) +target_compile_definitions(test_library_scatter_gather PRIVATE -DTEST_INPUT_FOLDER=${CMAKE_CURRENT_SOURCE_DIR}) +add_test(LibraryScatterGather test_library_scatter_gather) +set_tests_properties(LibraryScatterGather PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") + set(TEST_CONFIG_DEFS "-DTEST_INPUT_FOLDER=${CMAKE_CURRENT_SOURCE_DIR};-DLAMMPS_${LAMMPS_SIZES}") set(PKG_COUNT 0) foreach(PKG ${STANDARD_PACKAGES} ${SUFFIX_PACKAGES}) diff --git a/unittest/c-library/test_library_external.cpp b/unittest/c-library/test_library_external.cpp index 005b31fcab..15edd5f113 100644 --- a/unittest/c-library/test_library_external.cpp +++ b/unittest/c-library/test_library_external.cpp @@ -1,4 +1,4 @@ -// unit tests creating LAMMPS instances via the library interface +// unit tests for interfacing with fix external via the library interface #include "library.h" diff --git a/unittest/c-library/test_library_scatter_gather.cpp b/unittest/c-library/test_library_scatter_gather.cpp new file mode 100644 index 0000000000..34022f617e --- /dev/null +++ b/unittest/c-library/test_library_scatter_gather.cpp @@ -0,0 +1,133 @@ +// unit tests for testing scatter/gather operations through the library interface + +#include "lammps.h" +#include "library.h" +#include "lmptype.h" +#include + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include "test_main.h" + +#define STRINGIFY(val) XSTR(val) +#define XSTR(val) #val + +using ::LAMMPS_NS::bigint; +using ::LAMMPS_NS::tagint; +using ::testing::HasSubstr; +using ::testing::StartsWith; + +class GatherProperties : public ::testing::Test { +protected: + void *lmp; + std::string INPUT_DIR = STRINGIFY(TEST_INPUT_FOLDER); + + GatherProperties(){}; + ~GatherProperties() override{}; + + void SetUp() override + { + const char *args[] = {"LAMMPS_test", "-log", "none", + "-echo", "screen", "-nocite", + "-var", "input_dir", STRINGIFY(TEST_INPUT_FOLDER)}; + + char **argv = (char **)args; + int argc = sizeof(args) / sizeof(char *); + + ::testing::internal::CaptureStdout(); + lmp = lammps_open_no_mpi(argc, argv, NULL); + std::string output = ::testing::internal::GetCapturedStdout(); + if (verbose) std::cout << output; + EXPECT_THAT(output, StartsWith("LAMMPS (")); + } + void TearDown() override + { + ::testing::internal::CaptureStdout(); + lammps_close(lmp); + std::string output = ::testing::internal::GetCapturedStdout(); + EXPECT_THAT(output, HasSubstr("Total wall time:")); + if (verbose) std::cout << output; + lmp = nullptr; + } +}; + +TEST_F(GatherProperties, gather_bonds_newton_on) +{ + if (!lammps_has_style(lmp, "atom", "full")) GTEST_SKIP(); + std::string input = INPUT_DIR + PATH_SEP + "in.fourmol"; + if (!verbose) ::testing::internal::CaptureStdout(); + lammps_command(lmp, "newton on on"); + lammps_file(lmp, input.c_str()); + if (!verbose) ::testing::internal::GetCapturedStdout(); + + bigint nbonds = *(bigint *)lammps_extract_global(lmp, "nbonds"); + EXPECT_EQ(nbonds, 24); + + tagint *bonds = new tagint[3 * nbonds]; + lammps_gather_bonds(lmp, bonds); + +#define CHECK_BOND(idx, type, atom1, atom2) \ + if (((bonds[3 * idx + 1] == atom1) && (bonds[3 * idx + 2] == atom2)) || \ + ((bonds[3 * idx + 1] == atom2) && (bonds[3 * idx + 2] == atom1))) { \ + EXPECT_EQ(bonds[3 * idx], type); \ + ++count; \ + } + + // check validity of a few bonds by comparing the bond type and counting the matches. + int count = 0; + for (bigint i = 0; i < nbonds; ++i) { + CHECK_BOND(i, 5, 1, 2); + CHECK_BOND(i, 3, 1, 3); + CHECK_BOND(i, 2, 3, 4); + CHECK_BOND(i, 2, 3, 5); + CHECK_BOND(i, 1, 3, 6); + CHECK_BOND(i, 3, 6, 8); + CHECK_BOND(i, 4, 6, 7); + CHECK_BOND(i, 5, 8, 9); + CHECK_BOND(i, 5, 27, 28); + CHECK_BOND(i, 5, 27, 29); + } + EXPECT_EQ(count, 10); + delete[] bonds; +}; + +TEST_F(GatherProperties, gather_bonds_newton_off) +{ + if (!lammps_has_style(lmp, "atom", "full")) GTEST_SKIP(); + std::string input = INPUT_DIR + PATH_SEP + "in.fourmol"; + if (!verbose) ::testing::internal::CaptureStdout(); + lammps_command(lmp, "newton off off"); + lammps_file(lmp, input.c_str()); + if (!verbose) ::testing::internal::GetCapturedStdout(); + + bigint nbonds = *(bigint *)lammps_extract_global(lmp, "nbonds"); + EXPECT_EQ(nbonds, 24); + + tagint *bonds = new tagint[3 * nbonds]; + lammps_gather_bonds(lmp, bonds); + +#define CHECK_BOND(idx, type, atom1, atom2) \ + if (((bonds[3 * idx + 1] == atom1) && (bonds[3 * idx + 2] == atom2)) || \ + ((bonds[3 * idx + 1] == atom2) && (bonds[3 * idx + 2] == atom1))) { \ + EXPECT_EQ(bonds[3 * idx], type); \ + ++count; \ + } + + // check validity of a few bonds by comparing the bond type and counting the matches. + int count = 0; + for (bigint i = 0; i < nbonds; ++i) { + CHECK_BOND(i, 5, 1, 2); + CHECK_BOND(i, 3, 1, 3); + CHECK_BOND(i, 2, 3, 4); + CHECK_BOND(i, 2, 3, 5); + CHECK_BOND(i, 1, 3, 6); + CHECK_BOND(i, 3, 6, 8); + CHECK_BOND(i, 4, 6, 7); + CHECK_BOND(i, 5, 8, 9); + CHECK_BOND(i, 5, 27, 28); + CHECK_BOND(i, 5, 27, 29); + } + EXPECT_EQ(count, 10); + delete[] bonds; +};