Merge pull request #2642 from rbberger/balance_tests

MPI balancing testing
This commit is contained in:
Axel Kohlmeyer
2021-04-21 16:00:01 -04:00
committed by GitHub
5 changed files with 267 additions and 4 deletions

View File

@ -257,7 +257,7 @@ factor, similar to how the :doc:`fix balance shift <fix_balance>`
command operates. command operates.
The *dimstr* argument is a string of characters, each of which must be The *dimstr* argument is a string of characters, each of which must be
an "x" or "y" or "z". Eacn character can appear zero or one time, an "x" or "y" or "z". Each character can appear zero or one time,
since there is no advantage to balancing on a dimension more than since there is no advantage to balancing on a dimension more than
once. You should normally only list dimensions where you expect there once. You should normally only list dimensions where you expect there
to be a density variation in the particles. to be a density variation in the particles.
@ -285,7 +285,7 @@ plane gets closer to the target value.
After the balanced plane positions are determined, if any pair of After the balanced plane positions are determined, if any pair of
adjacent planes are closer together than the neighbor skin distance adjacent planes are closer together than the neighbor skin distance
(as specified by the :doc`neigh_modify <neigh_modify>` command), then (as specified by the :doc:`neigh_modify <neigh_modify>` command), then
the plane positions are shifted to separate them by at least this the plane positions are shifted to separate them by at least this
amount. This is to prevent particles being lost when dynamics are run amount. This is to prevent particles being lost when dynamics are run
with processor sub-domains that are too narrow in one or more with processor sub-domains that are too narrow in one or more

View File

@ -216,7 +216,7 @@ above. It changes the positions of cutting planes between processors
in an iterative fashion, seeking to reduce the imbalance factor. in an iterative fashion, seeking to reduce the imbalance factor.
The *dimstr* argument is a string of characters, each of which must be The *dimstr* argument is a string of characters, each of which must be
an "x" or "y" or "z". Eacn character can appear zero or one time, an "x" or "y" or "z". Each character can appear zero or one time,
since there is no advantage to balancing on a dimension more than since there is no advantage to balancing on a dimension more than
once. You should normally only list dimensions where you expect there once. You should normally only list dimensions where you expect there
to be a density variation in the particles. to be a density variation in the particles.

View File

@ -764,7 +764,6 @@ Dyre
Dzyaloshinskii Dzyaloshinskii
Eaa Eaa
Eaat Eaat
Eacn
eam eam
eangle eangle
earg earg

View File

@ -56,3 +56,10 @@ add_executable(test_reset_ids test_reset_ids.cpp)
target_compile_definitions(test_reset_ids PRIVATE -DTEST_INPUT_FOLDER=${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(test_reset_ids PRIVATE -DTEST_INPUT_FOLDER=${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(test_reset_ids PRIVATE lammps GTest::GMock GTest::GTest) target_link_libraries(test_reset_ids PRIVATE lammps GTest::GMock GTest::GTest)
add_test(NAME ResetIDs COMMAND test_reset_ids WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) add_test(NAME ResetIDs COMMAND test_reset_ids WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
if(BUILD_MPI)
add_executable(test_mpi_load_balancing test_mpi_load_balancing.cpp)
target_link_libraries(test_mpi_load_balancing PRIVATE lammps GTest::GTest GTest::GMock)
target_compile_definitions(test_mpi_load_balancing PRIVATE ${TEST_CONFIG_DEFS})
add_mpi_test(NAME MPILoadBalancing NUM_PROCS 4 COMMAND $<TARGET_FILE:test_mpi_load_balancing>)
endif()

View File

@ -0,0 +1,257 @@
// unit tests for checking LAMMPS MPI load balancing
#define LAMMPS_LIB_MPI 1
#include "lammps.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "neighbor.h"
#include "input.h"
#include "timer.h"
#include "info.h"
#include <string>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "../testing/test_mpi_main.h"
using ::testing::ExitedWithCode;
using ::testing::HasSubstr;
using ::testing::StartsWith;
using ::testing::StrEq;
namespace LAMMPS_NS
{
class MPILoadBalanceTest : public ::testing::Test {
public:
void command(const std::string &line) { lmp->input->one(line); }
protected:
const char *testbinary = "LAMMPSTest";
LAMMPS *lmp;
void SetUp() override
{
const char *args[] = {testbinary, "-log", "none", "-echo", "screen", "-nocite"};
char **argv = (char **)args;
int argc = sizeof(args) / sizeof(char *);
if (!verbose) ::testing::internal::CaptureStdout();
lmp = new LAMMPS(argc, argv, MPI_COMM_WORLD);
InitSystem();
if (!verbose) ::testing::internal::GetCapturedStdout();
}
virtual void InitSystem()
{
command("boundary f f f");
command("units lj");
command("atom_style atomic");
command("atom_modify map yes");
command("region box block 0 20 0 20 0 20");
command("create_box 1 box");
command("mass 1 1.0");
command("pair_style lj/cut 2.5");
command("pair_coeff 1 1 1.0 1.0 2.5");
command("neighbor 0.3 bin");
command("neigh_modify every 20 delay 0 check no");
}
void TearDown() override
{
if (!verbose) ::testing::internal::CaptureStdout();
delete lmp;
lmp = nullptr;
if (!verbose) ::testing::internal::GetCapturedStdout();
}
};
TEST_F(MPILoadBalanceTest, grid_yz)
{
command("create_atoms 1 single 0 0 0");
command("create_atoms 1 single 0 0 5");
command("create_atoms 1 single 0 5 0");
command("create_atoms 1 single 0 5 5");
command("create_atoms 1 single 5 0 0");
command("create_atoms 1 single 5 0 5");
command("create_atoms 1 single 5 5 0");
command("create_atoms 1 single 5 5 5");
ASSERT_EQ(lmp->atom->natoms, 8);
ASSERT_EQ(lmp->comm->nprocs, 4);
// initial state
switch(lmp->comm->me) {
case 0:
ASSERT_EQ(lmp->atom->nlocal, 8);
break;
case 1:
ASSERT_EQ(lmp->atom->nlocal, 0);
break;
case 2:
ASSERT_EQ(lmp->atom->nlocal, 0);
break;
case 3:
ASSERT_EQ(lmp->atom->nlocal, 0);
break;
}
command("balance 1 x uniform y 0.125 z uniform");
// state after balance command
switch(lmp->comm->me) {
case 0:
ASSERT_EQ(lmp->atom->nlocal, 4);
break;
case 1:
ASSERT_EQ(lmp->atom->nlocal, 0);
break;
case 2:
ASSERT_EQ(lmp->atom->nlocal, 4);
break;
case 3:
ASSERT_EQ(lmp->atom->nlocal, 0);
break;
}
command("balance 1 x uniform y 0.125 z 0.125");
// state after second balance command
switch(lmp->comm->me) {
case 0:
ASSERT_EQ(lmp->atom->nlocal, 2);
break;
case 1:
ASSERT_EQ(lmp->atom->nlocal, 2);
break;
case 2:
ASSERT_EQ(lmp->atom->nlocal, 2);
break;
case 3:
ASSERT_EQ(lmp->atom->nlocal, 2);
break;
}
}
TEST_F(MPILoadBalanceTest, rcb)
{
command("comm_style tiled");
command("create_atoms 1 single 0 0 0");
command("create_atoms 1 single 0 0 5");
command("create_atoms 1 single 0 5 0");
command("create_atoms 1 single 0 5 5");
command("create_atoms 1 single 5 0 0");
command("create_atoms 1 single 5 0 5");
command("create_atoms 1 single 5 5 0");
command("create_atoms 1 single 5 5 5");
// initial state
switch(lmp->comm->me) {
case 0:
ASSERT_EQ(lmp->atom->nlocal, 8);
break;
case 1:
ASSERT_EQ(lmp->atom->nlocal, 0);
break;
case 2:
ASSERT_EQ(lmp->atom->nlocal, 0);
break;
case 3:
ASSERT_EQ(lmp->atom->nlocal, 0);
break;
}
command("balance 1 rcb");
// state after balance command
switch(lmp->comm->me) {
case 0:
ASSERT_EQ(lmp->atom->nlocal, 2);
break;
case 1:
ASSERT_EQ(lmp->atom->nlocal, 2);
break;
case 2:
ASSERT_EQ(lmp->atom->nlocal, 2);
break;
case 3:
ASSERT_EQ(lmp->atom->nlocal, 2);
break;
}
// box dimensions should have minimal size
double dx = lmp->domain->subhi[0] - lmp->domain->sublo[0];
double dy = lmp->domain->subhi[1] - lmp->domain->sublo[1];
double dz = lmp->domain->subhi[2] - lmp->domain->sublo[2];
ASSERT_GT(dx, lmp->neighbor->skin);
ASSERT_GT(dy, lmp->neighbor->skin);
ASSERT_GT(dz, lmp->neighbor->skin);
}
TEST_F(MPILoadBalanceTest, rcb_min_size)
{
GTEST_SKIP();
// TODO minimum domain size is not enforced right now
// skipping for now to allow other MPI tests to get merged
command("comm_style tiled");
command("create_atoms 1 single 0 0 0");
command("create_atoms 1 single 0 0 0.25");
command("create_atoms 1 single 0 0.25 0");
command("create_atoms 1 single 0 0.25 0.25");
command("create_atoms 1 single 0.25 0 0");
command("create_atoms 1 single 0.25 0 0.25");
command("create_atoms 1 single 0.25 0.25 0");
command("create_atoms 1 single 0.25 0.25 0.25");
// initial state
switch(lmp->comm->me) {
case 0:
ASSERT_EQ(lmp->atom->nlocal, 8);
break;
case 1:
ASSERT_EQ(lmp->atom->nlocal, 0);
break;
case 2:
ASSERT_EQ(lmp->atom->nlocal, 0);
break;
case 3:
ASSERT_EQ(lmp->atom->nlocal, 0);
break;
}
// this should fail and not change the boxes
// or keep them at a minimum size
command("balance 1 rcb");
// state after balance command
switch(lmp->comm->me) {
case 0:
ASSERT_EQ(lmp->atom->nlocal, 8);
break;
case 1:
ASSERT_EQ(lmp->atom->nlocal, 0);
break;
case 2:
ASSERT_EQ(lmp->atom->nlocal, 0);
break;
case 3:
ASSERT_EQ(lmp->atom->nlocal, 0);
break;
}
// box dimensions should have minimal size
double dx = lmp->domain->subhi[0] - lmp->domain->sublo[0];
double dy = lmp->domain->subhi[1] - lmp->domain->sublo[1];
double dz = lmp->domain->subhi[2] - lmp->domain->sublo[2];
ASSERT_GT(dx, lmp->neighbor->skin);
ASSERT_GT(dy, lmp->neighbor->skin);
ASSERT_GT(dz, lmp->neighbor->skin);
}
}