add unit conversion to table pair style
This commit is contained in:
@ -44,6 +44,7 @@ PairTable::PairTable(LAMMPS *lmp) : Pair(lmp)
|
|||||||
{
|
{
|
||||||
ntables = 0;
|
ntables = 0;
|
||||||
tables = NULL;
|
tables = NULL;
|
||||||
|
unit_convert_flag = utils::get_supported_conversions(utils::ENERGY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
@ -360,6 +361,12 @@ void PairTable::read_table(Table *tb, char *file, char *keyword)
|
|||||||
{
|
{
|
||||||
TableFileReader reader(lmp, file, "pair");
|
TableFileReader reader(lmp, file, "pair");
|
||||||
|
|
||||||
|
// transparently convert units for supported conversions
|
||||||
|
|
||||||
|
int unit_convert = reader.get_unit_convert();
|
||||||
|
double conversion_factor = utils::get_conversion_factor(utils::ENERGY,
|
||||||
|
unit_convert);
|
||||||
|
|
||||||
char *line = reader.find_section_start(keyword);
|
char *line = reader.find_section_start(keyword);
|
||||||
|
|
||||||
if (!line) {
|
if (!line) {
|
||||||
@ -404,8 +411,8 @@ void PairTable::read_table(Table *tb, char *file, char *keyword)
|
|||||||
ValueTokenizer values(line);
|
ValueTokenizer values(line);
|
||||||
values.next_int();
|
values.next_int();
|
||||||
rfile = values.next_double();
|
rfile = values.next_double();
|
||||||
tb->efile[i] = values.next_double();
|
tb->efile[i] = conversion_factor * values.next_double();
|
||||||
tb->ffile[i] = values.next_double();
|
tb->ffile[i] = conversion_factor * values.next_double();
|
||||||
} catch (TokenizerException & e) {
|
} catch (TokenizerException & e) {
|
||||||
++cerror;
|
++cerror;
|
||||||
}
|
}
|
||||||
@ -461,29 +468,26 @@ void PairTable::read_table(Table *tb, char *file, char *keyword)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ferror) {
|
if (ferror)
|
||||||
std::string str = fmt::format("{} of {} force values in table are inconsistent with -dE/dr.\n"
|
error->warning(FLERR,fmt::format("{} of {} force values in table are "
|
||||||
" Should only be flagged at inflection points",ferror,tb->ninput);
|
"inconsistent with -dE/dr.\n Should "
|
||||||
error->warning(FLERR,str.c_str());
|
"only be flagged at inflection points",
|
||||||
}
|
ferror,tb->ninput));
|
||||||
|
|
||||||
// warn if re-computed distance values differ from file values
|
// warn if re-computed distance values differ from file values
|
||||||
|
|
||||||
if (rerror) {
|
if (rerror)
|
||||||
char str[128];
|
error->warning(FLERR,fmt::format("{} of {} distance values in table with "
|
||||||
sprintf(str,"%d of %d distance values in table with relative error\n"
|
"relative error\n over {} to "
|
||||||
" over %g to re-computed values",rerror,tb->ninput,EPSILONR);
|
"re-computed values",
|
||||||
error->warning(FLERR,str);
|
rerror,tb->ninput,EPSILONR));
|
||||||
}
|
|
||||||
|
|
||||||
// warn if data was read incompletely, e.g. columns were missing
|
// warn if data was read incompletely, e.g. columns were missing
|
||||||
|
|
||||||
if (cerror) {
|
if (cerror)
|
||||||
char str[128];
|
error->warning(FLERR,fmt::format("{} of {} lines in table were "
|
||||||
sprintf(str,"%d of %d lines in table were incomplete\n"
|
"incomplete\n or could not be parsed "
|
||||||
" or could not be parsed completely",cerror,tb->ninput);
|
"completely",cerror,tb->ninput));
|
||||||
error->warning(FLERR,str);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
|
|||||||
@ -28,8 +28,9 @@ using namespace LAMMPS_NS;
|
|||||||
|
|
||||||
TableFileReader::TableFileReader(LAMMPS *lmp,
|
TableFileReader::TableFileReader(LAMMPS *lmp,
|
||||||
const std::string &filename,
|
const std::string &filename,
|
||||||
const std::string &type) :
|
const std::string &type,
|
||||||
PotentialFileReader(lmp, filename, type + " table")
|
const int auto_convert) :
|
||||||
|
PotentialFileReader(lmp, filename, type + " table", auto_convert)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,8 @@ namespace LAMMPS_NS
|
|||||||
{
|
{
|
||||||
class TableFileReader : public PotentialFileReader {
|
class TableFileReader : public PotentialFileReader {
|
||||||
public:
|
public:
|
||||||
TableFileReader(class LAMMPS *lmp, const std::string &filename, const std::string & type);
|
TableFileReader(class LAMMPS *lmp, const std::string &filename,
|
||||||
|
const std::string &type, const int auto_convert = 0);
|
||||||
virtual ~TableFileReader();
|
virtual ~TableFileReader();
|
||||||
|
|
||||||
char *find_section_start(const std::string &keyword);
|
char *find_section_start(const std::string &keyword);
|
||||||
|
|||||||
@ -687,7 +687,7 @@ double utils::get_conversion_factor(const int property, const int conversion)
|
|||||||
} else if (conversion == METAL2REAL) {
|
} else if (conversion == METAL2REAL) {
|
||||||
return 23.060549;
|
return 23.060549;
|
||||||
} else if (conversion == REAL2METAL) {
|
} else if (conversion == REAL2METAL) {
|
||||||
return 0.04336410204284381954;
|
return 1.0/23.060549;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
|||||||
@ -140,6 +140,10 @@ TEST_F(PairUnitConvertTest, lj_cut)
|
|||||||
lmp->input->one("read_data test_pair_unit_convert.data");
|
lmp->input->one("read_data test_pair_unit_convert.data");
|
||||||
lmp->input->one("pair_style lj/cut 6.0");
|
lmp->input->one("pair_style lj/cut 6.0");
|
||||||
lmp->input->one("pair_coeff * * 0.01014286346782117 2.0");
|
lmp->input->one("pair_coeff * * 0.01014286346782117 2.0");
|
||||||
|
remove("test.table.metal");
|
||||||
|
lmp->input->one("pair_write 1 1 1000 r 0.1 6.0 test.table.metal lj_1_1");
|
||||||
|
lmp->input->one("pair_write 1 2 1000 r 0.1 6.0 test.table.metal lj_1_2");
|
||||||
|
lmp->input->one("pair_write 2 2 1000 r 0.1 6.0 test.table.metal lj_2_2");
|
||||||
lmp->input->one("run 0 post no");
|
lmp->input->one("run 0 post no");
|
||||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||||
|
|
||||||
@ -158,6 +162,10 @@ TEST_F(PairUnitConvertTest, lj_cut)
|
|||||||
lmp->input->one("read_data test_pair_unit_convert.data");
|
lmp->input->one("read_data test_pair_unit_convert.data");
|
||||||
lmp->input->one("pair_style lj/cut 6.0");
|
lmp->input->one("pair_style lj/cut 6.0");
|
||||||
lmp->input->one("pair_coeff * * 0.2339 2.0");
|
lmp->input->one("pair_coeff * * 0.2339 2.0");
|
||||||
|
remove("test.table.real");
|
||||||
|
lmp->input->one("pair_write 1 1 1000 r 0.1 6.0 test.table.real lj_1_1");
|
||||||
|
lmp->input->one("pair_write 1 2 1000 r 0.1 6.0 test.table.real lj_1_2");
|
||||||
|
lmp->input->one("pair_write 2 2 1000 r 0.1 6.0 test.table.real lj_2_2");
|
||||||
lmp->input->one("run 0 post no");
|
lmp->input->one("run 0 post no");
|
||||||
if (!verbose) ::testing::internal::GetCapturedStdout();
|
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||||
|
|
||||||
@ -216,6 +224,101 @@ TEST_F(PairUnitConvertTest, sw)
|
|||||||
EXPECT_NEAR(ev_convert * fold[i][j], f[i][j], fabs(f[i][j] * rel_error));
|
EXPECT_NEAR(ev_convert * fold[i][j], f[i][j], fabs(f[i][j] * rel_error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(PairUnitConvertTest, table_metal2real)
|
||||||
|
{
|
||||||
|
// check if the prerequisite pair style is available
|
||||||
|
if (!info->has_style("pair", "table")) GTEST_SKIP();
|
||||||
|
|
||||||
|
if (!verbose) ::testing::internal::CaptureStdout();
|
||||||
|
lmp->input->one("units metal");
|
||||||
|
lmp->input->one("read_data test_pair_unit_convert.data");
|
||||||
|
lmp->input->one("pair_style table linear 1000");
|
||||||
|
lmp->input->one("pair_coeff 1 1 test.table.metal lj_1_1");
|
||||||
|
lmp->input->one("pair_coeff 1 2 test.table.metal lj_1_2");
|
||||||
|
lmp->input->one("pair_coeff 2 2 test.table.metal lj_2_2");
|
||||||
|
lmp->input->one("run 0 post no");
|
||||||
|
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||||
|
|
||||||
|
// copy pressure, energy, and force from first step
|
||||||
|
double pold;
|
||||||
|
lmp->output->thermo->evaluate_keyword("press", &pold);
|
||||||
|
double eold = lmp->force->pair->eng_vdwl + lmp->force->pair->eng_coul;
|
||||||
|
double **f = lmp->atom->f;
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
for (int j = 0; j < 3; ++j)
|
||||||
|
fold[i][j] = f[i][j];
|
||||||
|
|
||||||
|
if (!verbose) ::testing::internal::CaptureStdout();
|
||||||
|
lmp->input->one("clear");
|
||||||
|
lmp->input->one("units real");
|
||||||
|
lmp->input->one("read_data test_pair_unit_convert.data");
|
||||||
|
lmp->input->one("pair_style table linear 1000");
|
||||||
|
lmp->input->one("pair_coeff 1 1 test.table.metal lj_1_1");
|
||||||
|
lmp->input->one("pair_coeff 1 2 test.table.metal lj_1_2");
|
||||||
|
lmp->input->one("pair_coeff 2 2 test.table.metal lj_2_2");
|
||||||
|
lmp->input->one("run 0 post no");
|
||||||
|
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||||
|
|
||||||
|
double pnew;
|
||||||
|
lmp->output->thermo->evaluate_keyword("press", &pnew);
|
||||||
|
EXPECT_NEAR(pold, p_convert * pnew, fabs(pnew * rel_error));
|
||||||
|
double enew = lmp->force->pair->eng_vdwl + lmp->force->pair->eng_coul;
|
||||||
|
EXPECT_NEAR(ev_convert * eold, enew, fabs(enew * rel_error));
|
||||||
|
|
||||||
|
f = lmp->atom->f;
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
for (int j = 0; j < 3; ++j)
|
||||||
|
EXPECT_NEAR(ev_convert * fold[i][j], f[i][j], fabs(f[i][j] * rel_error));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PairUnitConvertTest, table_real2metal)
|
||||||
|
{
|
||||||
|
// check if the prerequisite pair style is available
|
||||||
|
if (!info->has_style("pair", "table")) GTEST_SKIP();
|
||||||
|
|
||||||
|
if (!verbose) ::testing::internal::CaptureStdout();
|
||||||
|
lmp->input->one("units real");
|
||||||
|
lmp->input->one("read_data test_pair_unit_convert.data");
|
||||||
|
lmp->input->one("pair_style table linear 1000");
|
||||||
|
lmp->input->one("pair_coeff 1 1 test.table.real lj_1_1");
|
||||||
|
lmp->input->one("pair_coeff 1 2 test.table.real lj_1_2");
|
||||||
|
lmp->input->one("pair_coeff 2 2 test.table.real lj_2_2");
|
||||||
|
lmp->input->one("run 0 post no");
|
||||||
|
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||||
|
|
||||||
|
// copy pressure, energy, and force from first step
|
||||||
|
double pold;
|
||||||
|
lmp->output->thermo->evaluate_keyword("press", &pold);
|
||||||
|
double eold = lmp->force->pair->eng_vdwl + lmp->force->pair->eng_coul;
|
||||||
|
double **f = lmp->atom->f;
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
for (int j = 0; j < 3; ++j)
|
||||||
|
fold[i][j] = f[i][j];
|
||||||
|
|
||||||
|
if (!verbose) ::testing::internal::CaptureStdout();
|
||||||
|
lmp->input->one("clear");
|
||||||
|
lmp->input->one("units metal");
|
||||||
|
lmp->input->one("read_data test_pair_unit_convert.data");
|
||||||
|
lmp->input->one("pair_style table linear 1000");
|
||||||
|
lmp->input->one("pair_coeff 1 1 test.table.real lj_1_1");
|
||||||
|
lmp->input->one("pair_coeff 1 2 test.table.real lj_1_2");
|
||||||
|
lmp->input->one("pair_coeff 2 2 test.table.real lj_2_2");
|
||||||
|
lmp->input->one("run 0 post no");
|
||||||
|
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||||
|
|
||||||
|
double pnew;
|
||||||
|
lmp->output->thermo->evaluate_keyword("press", &pnew);
|
||||||
|
EXPECT_NEAR(pold, 1.0/p_convert * pnew, fabs(pnew * rel_error));
|
||||||
|
double enew = lmp->force->pair->eng_vdwl + lmp->force->pair->eng_coul;
|
||||||
|
EXPECT_NEAR(1.0/ev_convert * eold, enew, fabs(enew * rel_error));
|
||||||
|
|
||||||
|
f = lmp->atom->f;
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
for (int j = 0; j < 3; ++j)
|
||||||
|
EXPECT_NEAR(1.0/ev_convert * fold[i][j], f[i][j],
|
||||||
|
fabs(f[i][j] * rel_error));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(PairUnitConvertTest, tersoff)
|
TEST_F(PairUnitConvertTest, tersoff)
|
||||||
{
|
{
|
||||||
// check if the prerequisite pair style is available
|
// check if the prerequisite pair style is available
|
||||||
@ -539,5 +642,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
int rv = RUN_ALL_TESTS();
|
int rv = RUN_ALL_TESTS();
|
||||||
MPI_Finalize();
|
MPI_Finalize();
|
||||||
|
remove("test.table.metal");
|
||||||
|
remove("test.table.real");
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user