1 // unit tests for testing scatter/gather operations through the library interface
2 
3 #include "lammps.h"
4 #include "library.h"
5 #include "lmptype.h"
6 #include <string>
7 
8 #include "gmock/gmock.h"
9 #include "gtest/gtest.h"
10 
11 #include "test_main.h"
12 
13 #define STRINGIFY(val) XSTR(val)
14 #define XSTR(val) #val
15 
16 using ::LAMMPS_NS::bigint;
17 using ::LAMMPS_NS::tagint;
18 using ::testing::HasSubstr;
19 using ::testing::StartsWith;
20 
21 class GatherProperties : public ::testing::Test {
22 protected:
23     void *lmp;
24     std::string INPUT_DIR = STRINGIFY(TEST_INPUT_FOLDER);
25 
GatherProperties()26     GatherProperties(){};
~GatherProperties()27     ~GatherProperties() override{};
28 
SetUp()29     void SetUp() override
30     {
31         const char *args[] = {"LAMMPS_test", "-log",      "none",
32                               "-echo",       "screen",    "-nocite",
33                               "-var",        "input_dir", STRINGIFY(TEST_INPUT_FOLDER)};
34 
35         char **argv = (char **)args;
36         int argc    = sizeof(args) / sizeof(char *);
37 
38         ::testing::internal::CaptureStdout();
39         lmp                = lammps_open_no_mpi(argc, argv, NULL);
40         std::string output = ::testing::internal::GetCapturedStdout();
41         if (verbose) std::cout << output;
42         EXPECT_THAT(output, StartsWith("LAMMPS ("));
43     }
TearDown()44     void TearDown() override
45     {
46         ::testing::internal::CaptureStdout();
47         lammps_close(lmp);
48         std::string output = ::testing::internal::GetCapturedStdout();
49         EXPECT_THAT(output, HasSubstr("Total wall time:"));
50         if (verbose) std::cout << output;
51         lmp = nullptr;
52     }
53 };
54 
TEST_F(GatherProperties,gather_bonds_newton_on)55 TEST_F(GatherProperties, gather_bonds_newton_on)
56 {
57     if (!lammps_has_style(lmp, "atom", "full")) GTEST_SKIP();
58     std::string input = INPUT_DIR + PATH_SEP + "in.fourmol";
59     if (!verbose) ::testing::internal::CaptureStdout();
60     lammps_command(lmp, "newton on on");
61     lammps_file(lmp, input.c_str());
62     if (!verbose) ::testing::internal::GetCapturedStdout();
63 
64     bigint nbonds = *(bigint *)lammps_extract_global(lmp, "nbonds");
65     EXPECT_EQ(nbonds, 24);
66 
67     tagint *bonds = new tagint[3 * nbonds];
68     lammps_gather_bonds(lmp, bonds);
69 
70 #define CHECK_BOND(idx, type, atom1, atom2)                                 \
71     if (((bonds[3 * idx + 1] == atom1) && (bonds[3 * idx + 2] == atom2)) || \
72         ((bonds[3 * idx + 1] == atom2) && (bonds[3 * idx + 2] == atom1))) { \
73         EXPECT_EQ(bonds[3 * idx], type);                                    \
74         ++count;                                                            \
75     }
76 
77     // check validity of a few bonds by comparing the bond type and counting the matches.
78     int count = 0;
79     for (bigint i = 0; i < nbonds; ++i) {
80         CHECK_BOND(i, 5, 1, 2);
81         CHECK_BOND(i, 3, 1, 3);
82         CHECK_BOND(i, 2, 3, 4);
83         CHECK_BOND(i, 2, 3, 5);
84         CHECK_BOND(i, 1, 3, 6);
85         CHECK_BOND(i, 3, 6, 8);
86         CHECK_BOND(i, 4, 6, 7);
87         CHECK_BOND(i, 5, 8, 9);
88         CHECK_BOND(i, 5, 27, 28);
89         CHECK_BOND(i, 5, 27, 29);
90     }
91     EXPECT_EQ(count, 10);
92     delete[] bonds;
93 };
94 
TEST_F(GatherProperties,gather_bonds_newton_off)95 TEST_F(GatherProperties, gather_bonds_newton_off)
96 {
97     if (!lammps_has_style(lmp, "atom", "full")) GTEST_SKIP();
98     std::string input = INPUT_DIR + PATH_SEP + "in.fourmol";
99     if (!verbose) ::testing::internal::CaptureStdout();
100     lammps_command(lmp, "newton off off");
101     lammps_file(lmp, input.c_str());
102     if (!verbose) ::testing::internal::GetCapturedStdout();
103 
104     bigint nbonds = *(bigint *)lammps_extract_global(lmp, "nbonds");
105     EXPECT_EQ(nbonds, 24);
106 
107     tagint *bonds = new tagint[3 * nbonds];
108     lammps_gather_bonds(lmp, bonds);
109 
110 #define CHECK_BOND(idx, type, atom1, atom2)                                 \
111     if (((bonds[3 * idx + 1] == atom1) && (bonds[3 * idx + 2] == atom2)) || \
112         ((bonds[3 * idx + 1] == atom2) && (bonds[3 * idx + 2] == atom1))) { \
113         EXPECT_EQ(bonds[3 * idx], type);                                    \
114         ++count;                                                            \
115     }
116 
117     // check validity of a few bonds by comparing the bond type and counting the matches.
118     int count = 0;
119     for (bigint i = 0; i < nbonds; ++i) {
120         CHECK_BOND(i, 5, 1, 2);
121         CHECK_BOND(i, 3, 1, 3);
122         CHECK_BOND(i, 2, 3, 4);
123         CHECK_BOND(i, 2, 3, 5);
124         CHECK_BOND(i, 1, 3, 6);
125         CHECK_BOND(i, 3, 6, 8);
126         CHECK_BOND(i, 4, 6, 7);
127         CHECK_BOND(i, 5, 8, 9);
128         CHECK_BOND(i, 5, 27, 28);
129         CHECK_BOND(i, 5, 27, 29);
130     }
131     EXPECT_EQ(count, 10);
132     delete[] bonds;
133 };
134