Merge pull request #2477 from yafshar/kim_improvement

Misc. KIM updates
This commit is contained in:
Richard Berger
2020-11-29 12:17:17 -05:00
committed by GitHub
9 changed files with 589 additions and 422 deletions

View File

@ -92,7 +92,12 @@ void KimInit::command(int narg, char **arg)
strcpy(user_units,arg[1]); strcpy(user_units,arg[1]);
if (narg == 3) { if (narg == 3) {
if (strcmp(arg[2],"unit_conversion_mode")==0) unit_conversion_mode = true; if (strcmp(arg[2],"unit_conversion_mode")==0) unit_conversion_mode = true;
else { error->all(FLERR,"Illegal kim_init command"); } else {
error->all(FLERR,fmt::format("Illegal kim_init command.\nThe argument "
"followed by unit_style {} is an optional "
"argument and when is used must "
"be unit_conversion_mode", user_units));
}
} else unit_conversion_mode = false; } else unit_conversion_mode = false;
char *model_units; char *model_units;
@ -122,38 +127,41 @@ void get_kim_unit_names(
KIM_TimeUnit & timeUnit, KIM_TimeUnit & timeUnit,
Error * error) Error * error)
{ {
if ((strcmp(system,"real")==0)) { if (strcmp(system,"real") == 0) {
lengthUnit = KIM_LENGTH_UNIT_A; lengthUnit = KIM_LENGTH_UNIT_A;
energyUnit = KIM_ENERGY_UNIT_kcal_mol; energyUnit = KIM_ENERGY_UNIT_kcal_mol;
chargeUnit = KIM_CHARGE_UNIT_e; chargeUnit = KIM_CHARGE_UNIT_e;
temperatureUnit = KIM_TEMPERATURE_UNIT_K; temperatureUnit = KIM_TEMPERATURE_UNIT_K;
timeUnit = KIM_TIME_UNIT_fs; timeUnit = KIM_TIME_UNIT_fs;
} else if ((strcmp(system,"metal")==0)) { } else if (strcmp(system,"metal") == 0) {
lengthUnit = KIM_LENGTH_UNIT_A; lengthUnit = KIM_LENGTH_UNIT_A;
energyUnit = KIM_ENERGY_UNIT_eV; energyUnit = KIM_ENERGY_UNIT_eV;
chargeUnit = KIM_CHARGE_UNIT_e; chargeUnit = KIM_CHARGE_UNIT_e;
temperatureUnit = KIM_TEMPERATURE_UNIT_K; temperatureUnit = KIM_TEMPERATURE_UNIT_K;
timeUnit = KIM_TIME_UNIT_ps; timeUnit = KIM_TIME_UNIT_ps;
} else if ((strcmp(system,"si")==0)) { } else if (strcmp(system,"si") == 0) {
lengthUnit = KIM_LENGTH_UNIT_m; lengthUnit = KIM_LENGTH_UNIT_m;
energyUnit = KIM_ENERGY_UNIT_J; energyUnit = KIM_ENERGY_UNIT_J;
chargeUnit = KIM_CHARGE_UNIT_C; chargeUnit = KIM_CHARGE_UNIT_C;
temperatureUnit = KIM_TEMPERATURE_UNIT_K; temperatureUnit = KIM_TEMPERATURE_UNIT_K;
timeUnit = KIM_TIME_UNIT_s; timeUnit = KIM_TIME_UNIT_s;
} else if ((strcmp(system,"cgs")==0)) { } else if (strcmp(system,"cgs") == 0) {
lengthUnit = KIM_LENGTH_UNIT_cm; lengthUnit = KIM_LENGTH_UNIT_cm;
energyUnit = KIM_ENERGY_UNIT_erg; energyUnit = KIM_ENERGY_UNIT_erg;
chargeUnit = KIM_CHARGE_UNIT_statC; chargeUnit = KIM_CHARGE_UNIT_statC;
temperatureUnit = KIM_TEMPERATURE_UNIT_K; temperatureUnit = KIM_TEMPERATURE_UNIT_K;
timeUnit = KIM_TIME_UNIT_s; timeUnit = KIM_TIME_UNIT_s;
} else if ((strcmp(system,"electron")==0)) { } else if (strcmp(system,"electron") == 0) {
lengthUnit = KIM_LENGTH_UNIT_Bohr; lengthUnit = KIM_LENGTH_UNIT_Bohr;
energyUnit = KIM_ENERGY_UNIT_Hartree; energyUnit = KIM_ENERGY_UNIT_Hartree;
chargeUnit = KIM_CHARGE_UNIT_e; chargeUnit = KIM_CHARGE_UNIT_e;
temperatureUnit = KIM_TEMPERATURE_UNIT_K; temperatureUnit = KIM_TEMPERATURE_UNIT_K;
timeUnit = KIM_TIME_UNIT_fs; timeUnit = KIM_TIME_UNIT_fs;
} else if ((strcmp(system,"lj")==0)) { } else if (strcmp(system,"lj") == 0 ||
error->all(FLERR,"LAMMPS unit_style lj not supported by KIM models"); strcmp(system,"micro") ==0 ||
strcmp(system,"nano")==0) {
error->all(FLERR,fmt::format("LAMMPS unit_style {} not supported "
"by KIM models", system));
} else { } else {
error->all(FLERR,"Unknown unit_style"); error->all(FLERR,"Unknown unit_style");
} }
@ -171,19 +179,19 @@ void KimInit::determine_model_type_and_units(char * model_name,
KIM_TemperatureUnit temperatureUnit; KIM_TemperatureUnit temperatureUnit;
KIM_TimeUnit timeUnit; KIM_TimeUnit timeUnit;
int units_accepted; int units_accepted;
KIM_Collections * kim_Coll; KIM_Collections * collections;
KIM_CollectionItemType itemType; KIM_CollectionItemType itemType;
int kim_error = KIM_Collections_Create(&kim_Coll); int kim_error = KIM_Collections_Create(&collections);
if (kim_error) { if (kim_error)
error->all(FLERR,"Unable to access KIM Collections to find Model."); error->all(FLERR,"Unable to access KIM Collections to find Model");
}
kim_error = KIM_Collections_GetItemType(kim_Coll, model_name, &itemType); auto logID = fmt::format("{}_Collections", comm->me);
if (kim_error) { KIM_Collections_SetLogID(collections, logID.c_str());
error->all(FLERR,"KIM Model name not found.");
} kim_error = KIM_Collections_GetItemType(collections, model_name, &itemType);
KIM_Collections_Destroy(&kim_Coll); if (kim_error) error->all(FLERR,"KIM Model name not found");
KIM_Collections_Destroy(&collections);
if (KIM_CollectionItemType_Equal(itemType, if (KIM_CollectionItemType_Equal(itemType,
KIM_COLLECTION_ITEM_TYPE_portableModel)) { KIM_COLLECTION_ITEM_TYPE_portableModel)) {
@ -199,12 +207,13 @@ void KimInit::determine_model_type_and_units(char * model_name,
&units_accepted, &units_accepted,
&pkim); &pkim);
if (kim_error) if (kim_error) error->all(FLERR,"Unable to load KIM Simulator Model");
error->all(FLERR,"Unable to load KIM Simulator Model.");
model_type = MO; model_type = MO;
if (units_accepted) { if (units_accepted) {
logID = fmt::format("{}_Model", comm->me);
KIM_Model_SetLogID(pkim, logID.c_str());
*model_units = new char[strlen(user_units)+1]; *model_units = new char[strlen(user_units)+1];
strcpy(*model_units,user_units); strcpy(*model_units,user_units);
return; return;
@ -226,6 +235,8 @@ void KimInit::determine_model_type_and_units(char * model_name,
&units_accepted, &units_accepted,
&pkim); &pkim);
if (units_accepted) { if (units_accepted) {
logID = fmt::format("{}_Model", comm->me);
KIM_Model_SetLogID(pkim, logID.c_str());
*model_units = new char[strlen(systems[i])+1]; *model_units = new char[strlen(systems[i])+1];
strcpy(*model_units,systems[i]); strcpy(*model_units,systems[i]);
return; return;
@ -239,36 +250,39 @@ void KimInit::determine_model_type_and_units(char * model_name,
} }
} else if (KIM_CollectionItemType_Equal( } else if (KIM_CollectionItemType_Equal(
itemType, KIM_COLLECTION_ITEM_TYPE_simulatorModel)) { itemType, KIM_COLLECTION_ITEM_TYPE_simulatorModel)) {
KIM_SimulatorModel * kim_SM; KIM_SimulatorModel * simulatorModel;
kim_error = KIM_SimulatorModel_Create(model_name, &kim_SM); kim_error = KIM_SimulatorModel_Create(model_name, &simulatorModel);
if (kim_error) if (kim_error)
error->all(FLERR,"Unable to load KIM Simulator Model."); error->all(FLERR,"Unable to load KIM Simulator Model");
model_type = SM; model_type = SM;
logID = fmt::format("{}_SimulatorModel", comm->me);
KIM_SimulatorModel_SetLogID(simulatorModel, logID.c_str());
int sim_fields; int sim_fields;
int sim_lines; int sim_lines;
char const * sim_field; char const * sim_field;
char const * sim_value; char const * sim_value;
KIM_SimulatorModel_GetNumberOfSimulatorFields(kim_SM, &sim_fields); KIM_SimulatorModel_GetNumberOfSimulatorFields(simulatorModel, &sim_fields);
KIM_SimulatorModel_CloseTemplateMap(kim_SM); KIM_SimulatorModel_CloseTemplateMap(simulatorModel);
for (int i=0; i < sim_fields; ++i) { for (int i=0; i < sim_fields; ++i) {
KIM_SimulatorModel_GetSimulatorFieldMetadata( KIM_SimulatorModel_GetSimulatorFieldMetadata(
kim_SM,i,&sim_lines,&sim_field); simulatorModel, i, &sim_lines, &sim_field);
if (0 == strcmp(sim_field,"units")) { if (0 == strcmp(sim_field,"units")) {
KIM_SimulatorModel_GetSimulatorFieldLine(kim_SM,i,0,&sim_value); KIM_SimulatorModel_GetSimulatorFieldLine(
simulatorModel, i, 0, &sim_value);
int len=strlen(sim_value)+1; int len=strlen(sim_value)+1;
*model_units = new char[len]; strcpy(*model_units,sim_value); *model_units = new char[len];
strcpy(*model_units,sim_value);
break; break;
} }
} }
KIM_SimulatorModel_Destroy(&kim_SM); KIM_SimulatorModel_Destroy(&simulatorModel);
if ((! unit_conversion_mode) && (strcmp(*model_units, user_units)!=0)) { if ((! unit_conversion_mode) && (strcmp(*model_units, user_units)!=0)) {
std::string mesg("Incompatible units for KIM Simulator Model, " error->all(FLERR,fmt::format("Incompatible units for KIM Simulator Model"
"required units = "); ", required units = {}", *model_units));
mesg += *model_units;
error->all(FLERR,mesg);
} }
} }
} }
@ -295,13 +309,16 @@ void KimInit::do_init(char *model_name, char *user_units, char *model_units, KIM
KIM_SimulatorModel * simulatorModel; KIM_SimulatorModel * simulatorModel;
if (model_type == SM) { if (model_type == SM) {
int kim_error = int kim_error =
KIM_SimulatorModel_Create(model_name,&simulatorModel); KIM_SimulatorModel_Create(model_name, &simulatorModel);
if (kim_error) if (kim_error)
error->all(FLERR,"Unable to load KIM Simulator Model."); error->all(FLERR,"Unable to load KIM Simulator Model");
auto logID = fmt::format("{}_SimulatorModel", comm->me);
KIM_SimulatorModel_SetLogID(simulatorModel, logID.c_str());
char const *sim_name, *sim_version; char const *sim_name, *sim_version;
KIM_SimulatorModel_GetSimulatorNameAndVersion( KIM_SimulatorModel_GetSimulatorNameAndVersion(
simulatorModel,&sim_name, &sim_version); simulatorModel, &sim_name, &sim_version);
if (0 != strcmp(sim_name,"LAMMPS")) if (0 != strcmp(sim_name,"LAMMPS"))
error->all(FLERR,"Incompatible KIM Simulator Model"); error->all(FLERR,"Incompatible KIM Simulator Model");
@ -389,7 +406,7 @@ void KimInit::do_init(char *model_name, char *user_units, char *model_units, KIM
mesg += fmt::format(" {:<8} | {:<{}} | {:<10} | {}\n",i+1,str_name, mesg += fmt::format(" {:<8} | {:<{}} | {:<10} | {}\n",i+1,str_name,
max_len,data_type,extent); max_len,data_type,extent);
} }
} else mesg += "No mutable parameters. \n"; } else mesg += "No mutable parameters.\n";
KIM_Model_Destroy(&pkim); KIM_Model_Destroy(&pkim);
input->write_echo(mesg); input->write_echo(mesg);
@ -447,7 +464,7 @@ void KimInit::do_variables(const std::string &from, const std::string &to)
conversion_factor); conversion_factor);
if (ier != 0) if (ier != 0)
error->all(FLERR,fmt::format("Unable to obtain conversion factor: " error->all(FLERR,fmt::format("Unable to obtain conversion factor: "
"unit = {}; from = {}; to = {}.", "unit = {}; from = {}; to = {}",
units[i], from, to)); units[i], from, to));
variable->internal_set(v_unit,conversion_factor); variable->internal_set(v_unit,conversion_factor);
@ -461,23 +478,28 @@ void KimInit::do_variables(const std::string &from, const std::string &to)
void KimInit::write_log_cite(char *model_name) void KimInit::write_log_cite(char *model_name)
{ {
KIM_Collections * coll; KIM_Collections * collections;
int err = KIM_Collections_Create(&coll); int err = KIM_Collections_Create(&collections);
if (err) return; if (err) return;
auto logID = fmt::format("{}_Collections", comm->me);
KIM_Collections_SetLogID(collections, logID.c_str());
int extent; int extent;
if (model_type == MO) { if (model_type == MO) {
err = KIM_Collections_CacheListOfItemMetadataFiles( err = KIM_Collections_CacheListOfItemMetadataFiles(
coll,KIM_COLLECTION_ITEM_TYPE_portableModel,model_name,&extent); collections, KIM_COLLECTION_ITEM_TYPE_portableModel,
model_name,&extent);
} else if (model_type == SM) { } else if (model_type == SM) {
err = KIM_Collections_CacheListOfItemMetadataFiles( err = KIM_Collections_CacheListOfItemMetadataFiles(
coll,KIM_COLLECTION_ITEM_TYPE_simulatorModel,model_name,&extent); collections, KIM_COLLECTION_ITEM_TYPE_simulatorModel,
model_name, &extent);
} else { } else {
error->all(FLERR,"Unknown model type."); error->all(FLERR,"Unknown model type");
} }
if (err) { if (err) {
KIM_Collections_Destroy(&coll); KIM_Collections_Destroy(&collections);
return; return;
} }
@ -486,7 +508,8 @@ void KimInit::write_log_cite(char *model_name)
int availableAsString; int availableAsString;
char const * fileString; char const * fileString;
err = KIM_Collections_GetItemMetadataFile( err = KIM_Collections_GetItemMetadataFile(
coll,i,&fileName,nullptr,nullptr,&availableAsString,&fileString); collections, i, &fileName, nullptr, nullptr,
&availableAsString, &fileString);
if (err) continue; if (err) continue;
if (0 == strncmp("kimcite",fileName,7)) { if (0 == strncmp("kimcite",fileName,7)) {
@ -494,5 +517,5 @@ void KimInit::write_log_cite(char *model_name)
} }
} }
KIM_Collections_Destroy(&coll); KIM_Collections_Destroy(&collections);
} }

View File

@ -16,6 +16,7 @@
Ryan S. Elliott (UMN) Ryan S. Elliott (UMN)
Ellad B. Tadmor (UMN) Ellad B. Tadmor (UMN)
Ronald Miller (Carleton U) Ronald Miller (Carleton U)
Yaser Afshar (UMN)
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
@ -87,6 +88,7 @@ void KimInteractions::command(int narg, char **arg)
if (!domain->box_exist) if (!domain->box_exist)
error->all(FLERR,"Must use 'kim_interactions' command after " error->all(FLERR,"Must use 'kim_interactions' command after "
"simulation box is defined"); "simulation box is defined");
do_setup(narg,arg); do_setup(narg,arg);
} }
@ -98,7 +100,11 @@ void KimInteractions::do_setup(int narg, char **arg)
if ((narg == 1) && (0 == strcmp("fixed_types",arg[0]))) { if ((narg == 1) && (0 == strcmp("fixed_types",arg[0]))) {
fixed_types = true; fixed_types = true;
} else if (narg != atom->ntypes) { } else if (narg != atom->ntypes) {
error->all(FLERR,"Illegal kim_interactions command"); error->all(FLERR,fmt::format("Illegal kim_interactions command.\nThe "
"LAMMPS simulation has {} atom type(s), but "
"{} chemical species passed to the "
"kim_interactions command",
atom->ntypes, narg));
} else { } else {
fixed_types = false; fixed_types = false;
} }
@ -121,22 +127,20 @@ void KimInteractions::do_setup(int narg, char **arg)
input->write_echo("#=== BEGIN kim_interactions ==================================\n"); input->write_echo("#=== BEGIN kim_interactions ==================================\n");
if (simulatorModel) { if (simulatorModel) {
if (!fixed_types) { if (!fixed_types) {
std::string delimiter(""); std::string atom_type_sym_list =
std::string atom_type_sym_list; fmt::format("{}", fmt::join(arg, arg + narg, " "));
std::string atom_type_num_list;
for (int i = 0; i < narg; i++) { std::string atom_type_num_list =
atom_type_sym_list += delimiter + arg[i]; fmt::format("{}", species_to_atomic_no(arg[0]));
atom_type_num_list += delimiter + std::to_string(species_to_atomic_no(arg[i]));
delimiter = " "; for (int i = 1; i < narg; ++i)
} atom_type_num_list += fmt::format(" {}", species_to_atomic_no(arg[i]));
KIM_SimulatorModel_AddTemplateMap( KIM_SimulatorModel_AddTemplateMap(
simulatorModel,"atom-type-sym-list",atom_type_sym_list.c_str()); simulatorModel, "atom-type-sym-list", atom_type_sym_list.c_str());
KIM_SimulatorModel_AddTemplateMap( KIM_SimulatorModel_AddTemplateMap(
simulatorModel,"atom-type-num-list",atom_type_num_list.c_str()); simulatorModel, "atom-type-num-list", atom_type_num_list.c_str());
KIM_SimulatorModel_CloseTemplateMap(simulatorModel); KIM_SimulatorModel_CloseTemplateMap(simulatorModel);
// validate species selection // validate species selection
@ -150,14 +154,14 @@ void KimInteractions::do_setup(int narg, char **arg)
for (auto atom_type_sym : utils::split_words(atom_type_sym_list)) { for (auto atom_type_sym : utils::split_words(atom_type_sym_list)) {
species_is_supported = false; species_is_supported = false;
if (atom_type_sym == "NULL") continue; if (atom_type_sym == "NULL") continue;
for (int i=0; i < sim_num_species; ++i) { for (int i = 0; i < sim_num_species; ++i) {
KIM_SimulatorModel_GetSupportedSpecies(simulatorModel,i,&sim_species); KIM_SimulatorModel_GetSupportedSpecies(
simulatorModel, i, &sim_species);
if (atom_type_sym == sim_species) species_is_supported = true; if (atom_type_sym == sim_species) species_is_supported = true;
} }
if (!species_is_supported) { if (!species_is_supported) {
std::string msg = "Species '"; error->all(FLERR,fmt::format("Species '{}' is not supported by this "
msg += atom_type_sym + "' is not supported by this KIM Simulator Model"; "KIM Simulator Model", atom_type_sym));
error->all(FLERR,msg);
} }
} }
} else { } else {
@ -169,29 +173,39 @@ void KimInteractions::do_setup(int narg, char **arg)
int sim_fields, sim_lines; int sim_fields, sim_lines;
const char *sim_field, *sim_value; const char *sim_field, *sim_value;
KIM_SimulatorModel_GetNumberOfSimulatorFields(simulatorModel, &sim_fields); KIM_SimulatorModel_GetNumberOfSimulatorFields(simulatorModel, &sim_fields);
for (int i=0; i < sim_fields; ++i) { for (int i = 0; i < sim_fields; ++i) {
KIM_SimulatorModel_GetSimulatorFieldMetadata( KIM_SimulatorModel_GetSimulatorFieldMetadata(
simulatorModel,i,&sim_lines,&sim_field); simulatorModel, i, &sim_lines, &sim_field);
if (0 == strcmp(sim_field,"units")) { if (strcmp(sim_field,"units") == 0) {
KIM_SimulatorModel_GetSimulatorFieldLine(simulatorModel,i,0,&sim_value); KIM_SimulatorModel_GetSimulatorFieldLine(
if (0 != strcmp(sim_value,update->unit_style)) simulatorModel, i, 0, &sim_value);
if (strcmp(sim_value,update->unit_style) != 0)
error->all(FLERR,"Incompatible units for KIM Simulator Model"); error->all(FLERR,"Incompatible units for KIM Simulator Model");
} }
} }
int sim_model_idx=-1; bool no_model_definition = true;
for (int i=0; i < sim_fields; ++i) { for (int i = 0; i < sim_fields; ++i) {
KIM_SimulatorModel_GetSimulatorFieldMetadata( KIM_SimulatorModel_GetSimulatorFieldMetadata(
simulatorModel,i,&sim_lines,&sim_field); simulatorModel, i, &sim_lines, &sim_field);
if (0 == strcmp(sim_field,"model-defn")) { if (strcmp(sim_field,"model-defn") == 0) {
if (domain->periodicity[0]&&domain->periodicity[1]&&domain->periodicity[2]) input->one("variable kim_periodic equal 1"); if (domain->periodicity[0]&&
else if (domain->periodicity[0]&&domain->periodicity[1]&&!domain->periodicity[2]) input->one("variable kim_periodic equal 2"); domain->periodicity[1]&&
domain->periodicity[2])
input->one("variable kim_periodic equal 1");
else if (domain->periodicity[0]&&
domain->periodicity[1]&&
!domain->periodicity[2])
input->one("variable kim_periodic equal 2");
else input->one("variable kim_periodic equal 0"); else input->one("variable kim_periodic equal 0");
sim_model_idx = i;
for (int j=0; j < sim_lines; ++j) { // KIM Simulator Model has a Model definition
no_model_definition = false;
for (int j = 0; j < sim_lines; ++j) {
KIM_SimulatorModel_GetSimulatorFieldLine( KIM_SimulatorModel_GetSimulatorFieldLine(
simulatorModel,sim_model_idx,j,&sim_value); simulatorModel, i, j, &sim_value);
if (utils::strmatch(sim_value,"^KIM_SET_TYPE_PARAMETERS")) { if (utils::strmatch(sim_value,"^KIM_SET_TYPE_PARAMETERS")) {
// Notes regarding the KIM_SET_TYPE_PARAMETERS command // Notes regarding the KIM_SET_TYPE_PARAMETERS command
// * This is an INTERNAL command. // * This is an INTERNAL command.
@ -212,7 +226,7 @@ void KimInteractions::do_setup(int narg, char **arg)
} }
} }
if (sim_model_idx < 0) if (no_model_definition)
error->all(FLERR,"KIM Simulator Model has no Model definition"); error->all(FLERR,"KIM Simulator Model has no Model definition");
KIM_SimulatorModel_OpenAndInitializeTemplateMap(simulatorModel); KIM_SimulatorModel_OpenAndInitializeTemplateMap(simulatorModel);
@ -227,14 +241,9 @@ void KimInteractions::do_setup(int narg, char **arg)
// NOTE: all references to arg must appear before calls to input->one() // NOTE: all references to arg must appear before calls to input->one()
// as that will reset the argument vector. // as that will reset the argument vector.
std::string cmd1("pair_style kim "); auto cmd1 = fmt::format("pair_style kim {}", model_name);
cmd1 += model_name; auto cmd2 =
fmt::format("pair_coeff * * {}", fmt::join(arg, arg + narg, " "));
std::string cmd2("pair_coeff * * ");
for (int i=0; i < narg; ++i) {
cmd2 += arg[i];
cmd2 += " ";
}
input->one(cmd1); input->one(cmd1);
input->one(cmd2); input->one(cmd2);
@ -248,22 +257,25 @@ void KimInteractions::do_setup(int narg, char **arg)
void KimInteractions::KIM_SET_TYPE_PARAMETERS(const std::string &input_line) const void KimInteractions::KIM_SET_TYPE_PARAMETERS(const std::string &input_line) const
{ {
int nocomment;
auto words = utils::split_words(input_line); auto words = utils::split_words(input_line);
std::string key = words[1]; const std::string key = words[1];
if (key != "pair" && key != "charge")
error->one(FLERR,fmt::format("Unrecognized KEY {} for "
"KIM_SET_TYPE_PARAMETERS command", key));
std::string filename = words[2]; std::string filename = words[2];
std::vector<std::string> species(words.begin()+3,words.end()); std::vector<std::string> species(words.begin()+3,words.end());
if ((int)species.size() != atom->ntypes) if ((int)species.size() != atom->ntypes)
error->one(FLERR,"Incorrect args for KIM_SET_TYPE_PARAMETERS command"); error->one(FLERR,"Incorrect args for KIM_SET_TYPE_PARAMETERS command");
FILE *fp; FILE *fp = nullptr;
if (comm->me == 0) {
fp = fopen(filename.c_str(),"r"); fp = fopen(filename.c_str(),"r");
if (fp == nullptr) { if (fp == nullptr) error->one(FLERR,"Parameter file not found");
error->one(FLERR,"Parameter file not found");
} }
char line[MAXLINE],*ptr; char line[MAXLINE], *ptr;
int n, eof = 0; int n, eof = 0;
while (1) { while (1) {
@ -279,27 +291,24 @@ void KimInteractions::KIM_SET_TYPE_PARAMETERS(const std::string &input_line) con
MPI_Bcast(&n,1,MPI_INT,0,world); MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world); MPI_Bcast(line,n,MPI_CHAR,0,world);
nocomment = line[0] != '#'; if (ptr = strchr(line,'#')) *ptr = '\0';
if (strspn(line," \t\n\r") == strlen(line)) continue;
if(nocomment) {
words = utils::split_words(line); words = utils::split_words(line);
if (key == "pair") { if (key == "pair") {
for (int ia = 0; ia < atom->ntypes; ++ia) { for (int ia = 0; ia < atom->ntypes; ++ia) {
for (int ib = ia; ib < atom->ntypes; ++ib) for (int ib = ia; ib < atom->ntypes; ++ib)
if (((species[ia] == words[0]) && (species[ib] == words[1])) if (((species[ia] == words[0]) && (species[ib] == words[1]))
|| ((species[ib] == words[0]) && (species[ia] == words[1]))) || ((species[ib] == words[0]) && (species[ia] == words[1])))
input->one(fmt::format("pair_coeff {} {} {}",ia+1,ib+1,fmt::join(words.begin()+2,words.end()," "))); input->one(fmt::format("pair_coeff {} {} {}",ia+1,ib+1,
fmt::join(words.begin()+2,words.end()," ")));
} }
} else if (key == "charge") { } else {
for (int ia = 0; ia < atom->ntypes; ++ia) for (int ia = 0; ia < atom->ntypes; ++ia)
if (species[ia] == words[0]) if (species[ia] == words[0])
input->one(fmt::format("set type {} charge {}",ia+1,words[1])); input->one(fmt::format("set type {} charge {}",ia+1,words[1]));
} else {
error->one(FLERR,"Unrecognized KEY for KIM_SET_TYPE_PARAMETERS command");
} }
} }
}
fclose(fp);
} }
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */

View File

@ -57,6 +57,7 @@
#include "kim_param.h" #include "kim_param.h"
#include "comm.h"
#include "error.h" #include "error.h"
#include "fix_store_kim.h" #include "fix_store_kim.h"
#include "force.h" #include "force.h"
@ -65,8 +66,9 @@
#include "pair_kim.h" #include "pair_kim.h"
#include "variable.h" #include "variable.h"
#include <cstdlib>
#include <cstring> #include <cstring>
#include <sstream> #include <vector>
extern "C" extern "C"
{ {
@ -118,8 +120,11 @@ void get_kim_unit_names(
chargeUnit = KIM_CHARGE_UNIT_e; chargeUnit = KIM_CHARGE_UNIT_e;
temperatureUnit = KIM_TEMPERATURE_UNIT_K; temperatureUnit = KIM_TEMPERATURE_UNIT_K;
timeUnit = KIM_TIME_UNIT_fs; timeUnit = KIM_TIME_UNIT_fs;
} else if ((strcmp(system, "lj") == 0)) { } else if (strcmp(system,"lj") == 0 ||
error->all(FLERR, "LAMMPS unit_style lj not supported by KIM models"); strcmp(system,"micro") ==0 ||
strcmp(system,"nano")==0) {
error->all(FLERR,fmt::format("LAMMPS unit_style {} not supported "
"by KIM models", system));
} else } else
error->all(FLERR, "Unknown unit_style"); error->all(FLERR, "Unknown unit_style");
} }
@ -240,6 +245,9 @@ void KimParam::command(int narg, char **arg)
&pkim); &pkim);
if (kim_error) if (kim_error)
error->all(FLERR, "Unable to create KIM Portable Model"); error->all(FLERR, "Unable to create KIM Portable Model");
auto logID = fmt::format("{}_Model", comm->me);
KIM_Model_SetLogID(pkim, logID.c_str());
} }
} }
@ -253,7 +261,7 @@ void KimParam::command(int narg, char **arg)
// Parameter name // Parameter name
char *paramname = nullptr; char *paramname = nullptr;
// Variable name // Variable name
char *varname = nullptr; std::string varname;
// Loop over all the arguments // Loop over all the arguments
for (int i = 1; i < narg;) { for (int i = 1; i < narg;) {
@ -277,15 +285,13 @@ void KimParam::command(int narg, char **arg)
if (kim_error) if (kim_error)
error->all(FLERR, "KIM GetParameterMetadata returned error"); error->all(FLERR, "KIM GetParameterMetadata returned error");
if (strcmp(paramname, str_name) == 0) if (strcmp(paramname, str_name) == 0) break;
break;
} }
if (param_index >= numberOfParameters) { if (param_index >= numberOfParameters) {
std::string msg("Wrong argument in kim_param get command.\n"); auto msg = fmt::format("Wrong argument in kim_param get command.\n"
msg += "This Model does not have the requested '"; "This Model does not have the requested '{}' "
msg += paramname; "parameter", paramname);
msg += "' parameter";
error->all(FLERR, msg); error->all(FLERR, msg);
} }
@ -299,60 +305,53 @@ void KimParam::command(int narg, char **arg)
// Check to see if the indices range contains // Check to see if the indices range contains
// only integer numbers and/or range : // only integer numbers and/or range :
if (argtostr.find_first_not_of("0123456789:") != std::string::npos) { if (argtostr.find_first_not_of("0123456789:") != std::string::npos) {
std::string msg("Illegal index_range.\n"); auto msg = fmt::format("Illegal index_range.\nExpected integer "
msg += "Expected integer parameter(s) instead of '"; "parameter(s) instead of '{}' in "
msg += argtostr; "index_range", argtostr);
msg += "' in index_range";
error->all(FLERR, msg); error->all(FLERR, msg);
} }
std::string::size_type npos = argtostr.find(':'); std::string::size_type npos = argtostr.find(':');
if (npos != std::string::npos) { if (npos != std::string::npos) {
argtostr[npos] = ' '; argtostr[npos] = ' ';
std::stringstream str(argtostr); auto words = utils::split_words(argtostr);
str >> nlbound >> nubound; nlbound = atoi(words[0].c_str());
nubound = atoi(words[1].c_str());
if (nubound < 1 || nubound > extent || if (nubound < 1 || nubound > extent ||
nlbound < 1 || nlbound > nubound) { nlbound < 1 || nlbound > nubound) {
std::string msg("Illegal index_range '"); auto msg = fmt::format("Illegal index_range '{}-{}' for '{}' "
msg += std::to_string(nlbound) + "-"; "parameter with the extent of '{}'",
msg += std::to_string(nubound) + "' for '"; nlbound, nubound, paramname, extent);
msg += paramname;
msg += "' parameter with the extent of '";
msg += std::to_string(extent);
msg += "'";
error->all(FLERR, msg); error->all(FLERR, msg);
} }
} else { } else {
std::stringstream str(argtostr); nlbound = atoi(argtostr.c_str());
str >> nlbound;
if (nlbound < 1 || nlbound > extent) { if (nlbound < 1 || nlbound > extent) {
std::string msg("Illegal index '"); auto msg = fmt::format("Illegal index '{}' for '{}' parameter "
msg += std::to_string(nlbound) + "' for '"; "with the extent of '{}'", nlbound,
msg += paramname; paramname, extent);
msg += "' parameter with the extent of '";
msg += std::to_string(extent);
msg += "'";
error->all(FLERR, msg); error->all(FLERR, msg);
} }
nubound = nlbound; nubound = nlbound;
} }
} else { } else {
std::string msg("Wrong number of arguments in "); std::string msg("Wrong number of arguments in 'kim_param get' ");
msg += "'kim_param get' command.\n"; msg += "command.\nIndex range after parameter name is mandatory";
msg += "Index range after parameter name is mandatory";
error->all(FLERR, msg); error->all(FLERR, msg);
} }
int const nvars = nubound - nlbound + 1; int const nvars = nubound - nlbound + 1;
char **varsname = nullptr; std::vector<std::string> varsname;
if (i < narg) { if (i < narg) {
// Get the variable/variable_base name // Get the variable/variable_base name
varname = arg[i++]; varname = arg[i++];
} else { } else {
std::string msg("Wrong number of arguments in "); std::string msg("Wrong number of arguments in 'kim_param get' ");
msg += "'kim_param get' command.\n"; msg += "command.\nThe LAMMPS variable name is mandatory";
msg += "The LAMMPS variable name is mandatory";
error->all(FLERR, msg); error->all(FLERR, msg);
} }
@ -362,56 +361,47 @@ void KimParam::command(int narg, char **arg)
if (nvars > 1) { if (nvars > 1) {
if (i < narg) { if (i < narg) {
if (strcmp(arg[i], "split") == 0) { if (strcmp(arg[i], "split") == 0) {
varsname = new char *[nvars]; varsname.resize(nvars);
for (int j = 0, k = nlbound; j < nvars; ++j, ++k) { for (int j = 0, k = nlbound; j < nvars; ++j, ++k) {
std::stringstream str; varsname[j] = fmt::format("{}_{}", varname, k);
str << varname << "_" << k;
varsname[j] = const_cast<char *>(str.str().c_str());
} }
} else if (strcmp(arg[i], "list") == 0) { } else if (strcmp(arg[i], "list") == 0) {
list_requested = true; list_requested = true;
varsname = new char *[1]; varsname.resize(1);
varsname[0] = varname; varsname[0] = varname;
// Default explicit (optional) formatarg // Default explicit (optional) formatarg
} else if (i - 1 + nvars < narg) { } else if (i - 1 + nvars < narg) {
varsname = new char *[nvars]; varsname.resize(nvars);
--i; --i;
for (int j = 0; j < nvars; ++j, ++i) for (int j = 0; j < nvars; ++j, ++i) varsname[j] = arg[i];
varsname[j] = arg[i];
if (i < narg) { if (i < narg) {
if (strcmp(arg[i], "explicit") == 0) if (strcmp(arg[i], "explicit") == 0) ++i;
++i;
} }
} else { } else {
std::string msg("Wrong number of arguments in "); auto msg =
msg += "'kim_param get' command.\nThe LAMMPS '"; fmt::format("Wrong number of arguments in 'kim_param get' "
msg += std::to_string(nvars); "command.\nThe LAMMPS '{}' variable names or "
msg += "' variable names or '"; "'{} split' is mandatory", nvars, varname);
msg += varname;
msg += " split' is mandatory";
error->all(FLERR, msg); error->all(FLERR, msg);
} }
} else { } else {
std::string msg("Wrong number of arguments in "); auto msg =
msg += "'kim_param get' command.\nThe LAMMPS '"; fmt::format("Wrong number of arguments in 'kim_param get' "
msg += std::to_string(nvars); "command.\nThe LAMMPS '{}' variable names or "
msg += "' variable names or '"; "'{} split/list' is mandatory", nvars, varname);
msg += varname;
msg += " split/list' is mandatory";
error->all(FLERR, msg); error->all(FLERR, msg);
} }
} else { } else {
varsname = new char *[1]; varsname.resize(1);
if (i < narg) { if (i < narg) {
if (strcmp(arg[i], "split") == 0) { if (strcmp(arg[i], "split") == 0) {
std::stringstream str; varsname[0] = fmt::format("{}_{}", varname, nlbound);
str << varname << "_" << nlbound;
varsname[0] = const_cast<char *>(str.str().c_str());
++i; ++i;
} else { } else {
if ((strcmp(arg[i], "list") == 0) || if ((strcmp(arg[i], "list") == 0) ||
(strcmp(arg[i], "explicit") == 0)) (strcmp(arg[i], "explicit") == 0))
++i; ++i;
varsname[0] = varname; varsname[0] = varname;
} }
} else { } else {
@ -419,98 +409,90 @@ void KimParam::command(int narg, char **arg)
} }
} }
char **varcmd = new char *[3];
varcmd[1] = const_cast<char *>("string");
if (KIM_DataType_Equal(kim_DataType, KIM_DATA_TYPE_Double)) { if (KIM_DataType_Equal(kim_DataType, KIM_DATA_TYPE_Double)) {
if (list_requested) { if (list_requested) {
std::stringstream str; std::string str;
double V; double V;
{ {
kim_error = KIM_Model_GetParameterDouble(pkim, param_index, kim_error = KIM_Model_GetParameterDouble(pkim, param_index,
nlbound - 1, &V); nlbound - 1, &V);
if (kim_error) if (kim_error)
error->all(FLERR, "KIM GetParameterDouble returned error"); error->all(FLERR, "KIM GetParameterDouble returned error");
str << V;
str = fmt::format("{}", V);
} }
for (int j = 1; j < nvars; ++j) { for (int j = 1; j < nvars; ++j) {
kim_error = KIM_Model_GetParameterDouble(pkim, param_index, kim_error = KIM_Model_GetParameterDouble(pkim, param_index,
nlbound - 1 + j, &V); nlbound - 1 + j, &V);
if (kim_error) if (kim_error)
error->all(FLERR, "KIM GetParameterDouble returned error"); error->all(FLERR, "KIM GetParameterDouble returned error");
str << " " << V;
str += fmt::format(" {}", V);
} }
varcmd[0] = varsname[0];
varcmd[2] = const_cast<char *>(str.str().c_str()); auto setcmd = fmt::format("{} string {}", varsname[0], str);
input->variable->set(3, varcmd); input->variable->set(setcmd);
echo_var_assign(varcmd[0], varcmd[2]); input->write_echo(fmt::format("variable {}\n", setcmd));
} else { } else {
for (int j = 0; j < nvars; ++j) {
varcmd[0] = varsname[j];
double V; double V;
for (int j = 0; j < nvars; ++j) {
kim_error = KIM_Model_GetParameterDouble(pkim, param_index, kim_error = KIM_Model_GetParameterDouble(pkim, param_index,
nlbound - 1 + j, &V); nlbound - 1 + j, &V);
if (kim_error) if (kim_error)
error->all(FLERR, "KIM GetParameterDouble returned error"); error->all(FLERR, "KIM GetParameterDouble returned error");
std::stringstream str;
str << V; auto setcmd = fmt::format("{} string {}", varsname[j], V);
varcmd[2] = const_cast<char *>(str.str().c_str()); input->variable->set(setcmd);
input->variable->set(3, varcmd); input->write_echo(fmt::format("variable {}\n", setcmd));
echo_var_assign(varcmd[0], varcmd[2]);
} }
} }
} else if (KIM_DataType_Equal(kim_DataType, KIM_DATA_TYPE_Integer)) { } else if (KIM_DataType_Equal(kim_DataType, KIM_DATA_TYPE_Integer)) {
if (list_requested) { if (list_requested) {
std::stringstream str; std::string str;
int V; int V;
{ {
kim_error = KIM_Model_GetParameterInteger(pkim, param_index, kim_error = KIM_Model_GetParameterInteger(pkim, param_index,
nlbound - 1, &V); nlbound - 1, &V);
if (kim_error) if (kim_error)
error->all(FLERR, "KIM GetParameterInteger returned error"); error->all(FLERR, "KIM GetParameterInteger returned error");
str << V;
str = fmt::format("{}", V);
} }
for (int j = 1; j < nvars; ++j) { for (int j = 1; j < nvars; ++j) {
kim_error = KIM_Model_GetParameterInteger(pkim, param_index, kim_error = KIM_Model_GetParameterInteger(pkim, param_index,
nlbound - 1 + j, &V); nlbound - 1 + j, &V);
if (kim_error) if (kim_error)
error->all(FLERR, "KIM GetParameterInteger returned error"); error->all(FLERR, "KIM GetParameterInteger returned error");
str << " " << V;
str += fmt::format(" {}", V);
} }
varcmd[0] = varsname[0];
varcmd[2] = const_cast<char *>(str.str().c_str()); auto setcmd = fmt::format("{} string {}", varsname[0], str);
input->variable->set(3, varcmd); input->variable->set(setcmd);
echo_var_assign(varcmd[0], varcmd[2]); input->write_echo(fmt::format("variable {}\n", setcmd));
} else { } else {
for (int j = 0; j < nvars; ++j) {
varcmd[0] = varsname[j];
int V; int V;
for (int j = 0; j < nvars; ++j) {
kim_error = KIM_Model_GetParameterInteger(pkim, param_index, kim_error = KIM_Model_GetParameterInteger(pkim, param_index,
nlbound - 1 + j, &V); nlbound - 1 + j, &V);
if (kim_error) if (kim_error)
error->all(FLERR, "KIM GetParameterInteger returned error"); error->all(FLERR, "KIM GetParameterInteger returned error");
std::stringstream str;
str << V; auto setcmd = fmt::format("{} string {}", varsname[j], V);
varcmd[2] = const_cast<char *>(str.str().c_str()); input->variable->set(setcmd);
input->variable->set(3, varcmd); input->write_echo(fmt::format("variable {}\n", setcmd));
echo_var_assign(varcmd[0], varcmd[2]);
} }
} }
} else } else
error->all(FLERR, "Wrong parameter type"); error->all(FLERR, "Wrong parameter type");
delete[] varcmd;
delete[] varsname;
} // End of loop over all the arguments } // End of loop over all the arguments
// Set the parameters // Set the parameters
} else { } else {
std::string set_cmd("pair_coeff * * "); auto setcmd = fmt::format("pair_coeff * * {} {}", atom_type_list,
set_cmd += atom_type_list; fmt::join(arg + 1, arg + narg, " "));
for (int i = 1; i < narg; ++i) { input->one(setcmd);
set_cmd += " ";
set_cmd += arg[i];
}
input->one(set_cmd);
} }
} else } else
error->all(FLERR, "This model has No mutable parameters"); error->all(FLERR, "This model has No mutable parameters");
@ -521,12 +503,3 @@ void KimParam::command(int narg, char **arg)
input->write_echo(fmt::format("#=== END kim-param {} =====================" input->write_echo(fmt::format("#=== END kim-param {} ====================="
"==================\n",kim_param_get_set)); "==================\n",kim_param_get_set));
} }
/* ---------------------------------------------------------------------- */
void KimParam::echo_var_assign(const std::string &name,
const std::string &value) const
{
input->write_echo(fmt::format("variable {} string {}\n",
name, value));
}

View File

@ -77,9 +77,6 @@ public:
~KimParam(); ~KimParam();
void command(int, char **); void command(int, char **);
private:
void echo_var_assign(const std::string &name, const std::string &value) const;
}; };
} // namespace LAMMPS_NS } // namespace LAMMPS_NS

View File

@ -100,11 +100,7 @@ void kimProperty::command(int narg, char **arg)
error->all(FLERR, msg); error->all(FLERR, msg);
} }
if (comm->me == 0) { input->write_echo("#=== kim-property ===========================================\n");
std::string msg;
msg = "#=== kim-property ===========================================\n";
input->write_echo(msg);
}
// Get the kim_str ptr to the data associated with a kim_property_str // Get the kim_str ptr to the data associated with a kim_property_str
// variable // variable

View File

@ -63,11 +63,15 @@
#include "info.h" #include "info.h"
#include "input.h" #include "input.h"
#include "modify.h" #include "modify.h"
#include "utils.h"
#include "variable.h" #include "variable.h"
#include "version.h" #include "version.h"
#include "tokenizer.h"
#include "fmt/format.h"
#include <cstdlib>
#include <cstring> #include <cstring>
#include <sstream> #include <string>
#if defined(LMP_KIM_CURL) #if defined(LMP_KIM_CURL)
#include <sys/types.h> #include <sys/types.h>
@ -92,26 +96,28 @@ static size_t write_callback(void *, size_t, size_t, void *);
void KimQuery::command(int narg, char **arg) void KimQuery::command(int narg, char **arg)
{ {
char *varname, *function, *value;
if (narg < 2) error->all(FLERR,"Illegal kim_query command"); if (narg < 2) error->all(FLERR,"Illegal kim_query command");
// check if we had a kim_init command by finding fix STORE/KIM // check if we had a kim_init command by finding fix STORE/KIM
// retrieve model name. // retrieve model name.
char * model_name; char *model_name;
int ifix = modify->find_fix("KIM_MODEL_STORE"); const int ifix = modify->find_fix("KIM_MODEL_STORE");
if (ifix >= 0) { if (ifix >= 0) {
FixStoreKIM *fix_store = (FixStoreKIM *) modify->fix[ifix]; FixStoreKIM *fix_store = (FixStoreKIM *) modify->fix[ifix];
model_name = (char *)fix_store->getptr("model_name"); model_name = (char *)fix_store->getptr("model_name");
} else error->all(FLERR,"Must use 'kim_init' before 'kim_query'"); } else error->all(FLERR,"Must use 'kim_init' before 'kim_query'");
varname = arg[0]; char *varname = arg[0];
bool split = false; bool split = false;
if (0 == strcmp("split",arg[1])) { if (strcmp("split",arg[1]) == 0) {
if (narg == 2) error->all(FLERR,"Illegal kim_query command"); if (narg == 2) error->all(FLERR,"Illegal kim_query command.\nThe keyword "
if (0 == strcmp("list",arg[2])) "'split' must be followed by the name of "
error->all(FLERR,"Illegal kim_query command"); "the query function");
if (strcmp("list",arg[2]) == 0)
error->all(FLERR,"Illegal kim_query command.\nThe 'list' keyword "
"can not be used after 'split'");
split = true; split = true;
arg++; arg++;
narg--; narg--;
@ -119,74 +125,65 @@ void KimQuery::command(int narg, char **arg)
// The “list” is the default setting // The “list” is the default setting
// the result is returned as a space-separated list of values in variable // the result is returned as a space-separated list of values in variable
if (0 == strcmp("list",arg[1])) { if (strcmp("list",arg[1]) == 0) {
if (narg == 2) error->all(FLERR,"Illegal kim_query command"); if (narg == 2) error->all(FLERR,"Illegal kim_query command.\nThe 'list' "
if (split) error->all(FLERR,"Illegal kim_query command"); "keyword must be followed by ('split' "
"and) the name of the query function");
arg++; arg++;
narg--; narg--;
} }
function = arg[1];
for (int i = 2; i < narg; ++i) {
if (0 == strncmp("model=",arg[i], 6)) {
error->all(FLERR,"Illegal 'model' key in kim_query command");
}
}
char *function = arg[1];
for (int i = 2; i < narg; ++i) {
if (strncmp("model=",arg[i],6) == 0)
error->all(FLERR,"Illegal 'model' key in kim_query command");
if (!strchr(arg[i], '=') || !strchr(arg[i], '[') || !strchr(arg[i], ']'))
error->all(FLERR,fmt::format("Illegal query format.\nInput argument of "
"`{}` to kim_query is wrong. The query "
"format is the keyword=[value], where value "
"is always an array of one or more "
"comma-separated items", arg[i]));
}
#if defined(LMP_KIM_CURL) #if defined(LMP_KIM_CURL)
value = do_query(function, model_name, narg-2, arg+2, comm->me, world); char *value = do_query(function, model_name, narg-2, arg+2, comm->me, world);
// check for valid result // check for valid result
// on error the content of "value" is a '\0' byte // on error the content of "value" is a '\0' byte
// as the first element, and then the error message // as the first element, and then the error message
// that was returned by the web server // that was returned by the web server
char errmsg[1024]; if (strlen(value) == 0) {
if (0 == strlen(value)) { error->all(FLERR,fmt::format("OpenKIM query failed: {}", value+1));
sprintf(errmsg,"OpenKIM query failed: %s",value+1); } else if (strcmp(value,"EMPTY") == 0) {
error->all(FLERR,errmsg); error->all(FLERR,fmt::format("OpenKIM query returned no results"));
} else if (0 == strcmp(value,"EMPTY")) {
sprintf(errmsg,"OpenKIM query returned no results");
error->all(FLERR,errmsg);
} }
input->write_echo("#=== BEGIN kim-query =========================================\n"); input->write_echo("#=== BEGIN kim-query =========================================\n");
char **varcmd = new char*[3]; ValueTokenizer values(value, ",");
varcmd[1] = (char *) "string";
std::stringstream ss(value);
std::string token;
if (split) { if (split) {
int counter = 1; int counter = 1;
while(std::getline(ss, token, ',')) { while (values.has_next()) {
token.erase(0,token.find_first_not_of(" \n\r\t")); // ltrim auto svalue = values.next_string();
token.erase(token.find_last_not_of(" \n\r\t") + 1); // rtrim auto setcmd = fmt::format("{}_{} string {}", varname, counter++, svalue);
std::stringstream splitname; input->variable->set(setcmd);
splitname << varname << "_" << counter++; input->write_echo(fmt::format("variable {}\n", setcmd));
varcmd[0] = const_cast<char *>(splitname.str().c_str());
varcmd[2] = const_cast<char *>(token.c_str());
input->variable->set(3,varcmd);
echo_var_assign(splitname.str(), varcmd[2]);
} }
} else { } else {
varcmd[0] = varname; auto svalue = values.next_string();
std::string value_string; std::string setcmd = fmt::format("{} string \"{}", varname, svalue);
while(std::getline(ss, token, ',')) { while (values.has_next()) {
token.erase(0,token.find_first_not_of(" \n\r\t")); // ltrim svalue = values.next_string();
token.erase(token.find_last_not_of(" \n\r\t") + 1); // rtrim setcmd += fmt::format(" {}", svalue);
if (value_string.size() && token.size())
value_string += " ";
value_string += token;
} }
varcmd[2] = const_cast<char *>(value_string.c_str());; setcmd += "\"";
input->variable->set(3,varcmd); input->variable->set(setcmd);
echo_var_assign(varname, value_string); input->write_echo(fmt::format("variable {}\n", setcmd));
} }
input->write_echo("#=== END kim-query ===========================================\n\n"); input->write_echo("#=== END kim-query ===========================================\n\n");
delete[] varcmd;
delete[] value; delete[] value;
#else #else
error->all(FLERR,"Cannot use 'kim_query' command when KIM package " error->all(FLERR,"Cannot use 'kim_query' command when KIM package "
@ -201,17 +198,18 @@ void KimQuery::command(int narg, char **arg)
size_t write_callback(void *data, size_t size, size_t nmemb, void *userp) size_t write_callback(void *data, size_t size, size_t nmemb, void *userp)
{ {
struct WriteBuf *buf = (struct WriteBuf *)userp; struct WriteBuf *buf = (struct WriteBuf *)userp;
size_t buffer_size = size*nmemb;
// copy chunks into the buffer for as long as there is space left // copy chunks into the buffer for as long as there is space left
if (buf->sizeleft) { if (buf->sizeleft) {
size_t copy_this_much = buf->sizeleft; const size_t buffer_size = size * nmemb;
if (copy_this_much > buffer_size) const size_t copy_this_much =
copy_this_much = buffer_size; buf->sizeleft > buffer_size ? buffer_size : buf->sizeleft;
memcpy(buf->dataptr, data, copy_this_much); memcpy(buf->dataptr, data, copy_this_much);
buf->dataptr += copy_this_much; buf->dataptr += copy_this_much;
buf->sizeleft -= copy_this_much; buf->sizeleft -= copy_this_much;
return copy_this_much; return copy_this_much;
} }
return 0; // done return 0; // done
@ -220,16 +218,12 @@ size_t write_callback(void *data, size_t size, size_t nmemb, void *userp)
char *do_query(char *qfunction, char * model_name, int narg, char **arg, char *do_query(char *qfunction, char * model_name, int narg, char **arg,
int rank, MPI_Comm comm) int rank, MPI_Comm comm)
{ {
char value[512], *retval; char value[512];
// run the web query from rank 0 only // run the web query from rank 0 only
if (rank == 0) { if (rank == 0) {
CURL *handle;
CURLcode res;
// set up and clear receive buffer // set up and clear receive buffer
struct WriteBuf buf; struct WriteBuf buf;
buf.dataptr = value; buf.dataptr = value;
buf.sizeleft = 511; buf.sizeleft = 511;
@ -237,19 +231,43 @@ char *do_query(char *qfunction, char * model_name, int narg, char **arg,
// create curl web query instance // create curl web query instance
curl_global_init(CURL_GLOBAL_DEFAULT); curl_global_init(CURL_GLOBAL_DEFAULT);
handle = curl_easy_init(); CURL *handle = curl_easy_init();
if (handle) { if (handle) {
std::string url("https://query.openkim.org/api/"); auto url = fmt::format("https://query.openkim.org/api/{}", qfunction);
url += qfunction; auto query = fmt::format("model=[\"{}\"]", model_name);
for (int i = 0; i < narg; ++i) {
std::string query(arg[0]); ValueTokenizer values(arg[i], "=[]");
query += "&model=[\""; std::string key = values.next_string();
query += model_name; std::string val = values.next_string();
query += "\"]"; std::string::size_type n = val.find(",");
for (int i=1; i < narg; ++i) { if (n == std::string::npos) {
query += '&'; if (utils::is_integer(val) ||
query += arg[i]; utils::is_double(val) ||
(val.front() == '"' &&
val.back() == '"')) {
query += fmt::format("&{}", arg[i]);
} else {
query += fmt::format("&{}=[\"{}\"]", key, val);
}
} else {
query += fmt::format("&{}=[", key);
while (n != std::string::npos){
std::string sval = val.substr(0, n);
if (utils::is_integer(sval) ||
utils::is_double(sval) ||
(val.front() == '"' &&
val.back() == '"')) {
query += fmt::format("{},", sval);
} else {
query += fmt::format("\"{}\",", sval);
}
val = val.substr(n + 1);
n = val.find(",");
}
if (val.size()) query += fmt::format("\"{}\"]", val);
else query[query.size() - 1]=']';
}
} }
#if LMP_DEBUG_CURL #if LMP_DEBUG_CURL
@ -274,23 +292,21 @@ char *do_query(char *qfunction, char * model_name, int narg, char **arg,
} }
} }
std::string user_agent = std::string("kim_query--LAMMPS/") std::string user_agent = fmt::format("kim_query--LAMMPS/{} ({})",
+ LAMMPS_VERSION LAMMPS_VERSION, Info::get_os_info());
+ " (" + Info::get_os_info() + ")";
curl_easy_setopt(handle, CURLOPT_USERAGENT, user_agent.c_str());
curl_easy_setopt(handle, CURLOPT_USERAGENT, user_agent.c_str());
curl_easy_setopt(handle, CURLOPT_URL, url.c_str()); curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(handle, CURLOPT_POSTFIELDS, query.c_str()); curl_easy_setopt(handle, CURLOPT_POSTFIELDS, query.c_str());
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION,write_callback);
curl_easy_setopt(handle, CURLOPT_WRITEDATA,&buf); curl_easy_setopt(handle, CURLOPT_WRITEDATA,&buf);
// perform OpenKIM query and check for errors // perform OpenKIM query and check for errors
res = curl_easy_perform(handle); CURLcode res = curl_easy_perform(handle);
if (res != CURLE_OK) { if (res != CURLE_OK) {
// on error we return an "empty" string but add error message after it // on error we return an "empty" string but add error message after it
value[0]= '\0'; value[0] = '\0';
strcpy(value+1,curl_easy_strerror(res)); strcpy(value+1,curl_easy_strerror(res));
} }
curl_easy_cleanup(handle); curl_easy_cleanup(handle);
@ -302,30 +318,31 @@ char *do_query(char *qfunction, char * model_name, int narg, char **arg,
// we must make a proper copy of the query, as the stack allocation // we must make a proper copy of the query, as the stack allocation
// for "value" will go out of scope. a valid query has a '[' as // for "value" will go out of scope. a valid query has a '[' as
// the first character. skip over it (and the last character ']', too) // the first character. skip over it (and the last character ']', too)
// an error messages starts with a '\0' character. copy that and // an error message starts with a '\0' character. copy that and
// the remaining string, as that is the error message. // the remaining string, as that is the error message.
char *retval;
// a valid query has a '[' as the first character
if (value[0] == '[') { if (value[0] == '[') {
int len = strlen(value)-1; int len = strlen(value) - 1;
if (value[len] == ']') { if (value[len] == ']') {
retval = new char[len];
value[len] = '\0'; value[len] = '\0';
if (0 == strcmp(value+1, "")) { retval = new char[len];
strcpy(retval,"EMPTY"); if (strcmp(value+1, "") == 0) strcpy(retval,"EMPTY");
} else else strcpy(retval,value+1);
strcpy(retval,value+1);
} else { } else {
retval = new char[len+2]; retval = new char[len+2];
retval[0] = '\0'; retval[0] = '\0';
strcpy(retval+1,value); strcpy(retval+1,value);
} }
// an error message starts with a '\0' character
} else if (value[0] == '\0') { } else if (value[0] == '\0') {
int len = strlen(value+1)+2; int len = strlen(value+1)+2;
retval = new char[len]; retval = new char[len];
retval[0] = '\0'; retval[0] = '\0';
strcpy(retval+1,value+1); strcpy(retval+1,value+1);
} else {
// unknown response type. we should not get here. // unknown response type. we should not get here.
} else {
// we return an "empty" string but add error message after it // we return an "empty" string but add error message after it
int len = strlen(value)+2; int len = strlen(value)+2;
retval = new char[len]; retval = new char[len];
@ -335,11 +352,3 @@ char *do_query(char *qfunction, char * model_name, int narg, char **arg,
return retval; return retval;
} }
#endif #endif
/* ---------------------------------------------------------------------- */
void KimQuery::echo_var_assign(const std::string &name,
const std::string &value) const
{
input->write_echo(fmt::format("variable {} string {}\n",name,value));
}

View File

@ -13,7 +13,8 @@
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
Contributing authors: Axel Kohlmeyer (Temple U), Contributing authors: Axel Kohlmeyer (Temple U),
Ryan S. Elliott (UMN) Ryan S. Elliott (UMN),
Yaser Afshar (UMN)
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
@ -71,9 +72,6 @@ class KimQuery : protected Pointers {
public: public:
KimQuery(class LAMMPS *lmp) : Pointers(lmp) {}; KimQuery(class LAMMPS *lmp) : Pointers(lmp) {};
void command(int, char **); void command(int, char **);
private:
void echo_var_assign(const std::string &name, const std::string &value)
const;
}; };
} }

View File

@ -67,8 +67,9 @@
#include "neighbor.h" #include "neighbor.h"
#include "update.h" #include "update.h"
#include <cstdlib>
#include <cstring> #include <cstring>
#include <sstream> #include <vector>
using namespace LAMMPS_NS; using namespace LAMMPS_NS;
@ -204,8 +205,8 @@ void PairKIM::compute(int eflag, int vflag)
KIM_COMPUTE_ARGUMENT_NAME_particleContributing, KIM_COMPUTE_ARGUMENT_NAME_particleContributing,
kim_particleContributing); kim_particleContributing);
if (kimerror) if (kimerror)
error->all(FLERR, error->all(FLERR,"Unable to set KIM particle species "
"Unable to set KIM particle species codes and/or contributing"); "codes and/or contributing");
} }
// kim_particleSpecies = KIM atom species for each LAMMPS atom // kim_particleSpecies = KIM atom species for each LAMMPS atom
@ -339,7 +340,9 @@ void PairKIM::coeff(int narg, char **arg)
// insure I,J args are * * // insure I,J args are * *
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0) if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
error->all(FLERR,"Incorrect args for pair coefficients"); error->all(FLERR,"Incorrect args for pair coefficients.\nThe first two "
"arguments of pair_coeff command must be * * to span "
"all LAMMPS atom types");
int ilo,ihi,jlo,jhi; int ilo,ihi,jlo,jhi;
utils::bounds(FLERR,arg[0],1,atom->ntypes,ilo,ihi,error); utils::bounds(FLERR,arg[0],1,atom->ntypes,ilo,ihi,error);
@ -410,9 +413,8 @@ void PairKIM::coeff(int narg, char **arg)
if (supported) { if (supported) {
kim_particle_codes[i] = code; kim_particle_codes[i] = code;
} else { } else {
std::string msg("create_kim_particle_codes: symbol not found: "); error->all(FLERR,fmt::format("GetSpeciesSupportAndCode: symbol not "
msg += lmps_unique_elements[i]; "found: {}",lmps_unique_elements[i]));
error->all(FLERR, msg);
} }
} }
// Set the new values for PM parameters // Set the new values for PM parameters
@ -421,11 +423,9 @@ void PairKIM::coeff(int narg, char **arg)
int numberOfParameters(0); int numberOfParameters(0);
KIM_Model_GetNumberOfParameters(pkim, &numberOfParameters); KIM_Model_GetNumberOfParameters(pkim, &numberOfParameters);
if (!numberOfParameters) { if (!numberOfParameters)
std::string msg("Incorrect args for pair coefficients \n"); error->all(FLERR,"Incorrect args for pair coefficients\n"
msg += "This model has No mutable parameters"; "This model has No mutable parameters");
error->all(FLERR, msg);
}
int kimerror; int kimerror;
@ -456,11 +456,10 @@ void PairKIM::coeff(int narg, char **arg)
} }
if (param_index >= numberOfParameters) { if (param_index >= numberOfParameters) {
std::string msg("Wrong argument for pair coefficients.\n"); auto msg = fmt::format("Wrong argument for pair coefficients.\n"
msg += "This Model does not have the requested '"; "This Model does not have the requested "
msg += paramname; "'{}' parameter", paramname);
msg += "' parameter"; error->all(FLERR,msg);
error->all(FLERR, msg);
} }
// Get the index_range for the requested parameter // Get the index_range for the requested parameter
@ -472,48 +471,41 @@ void PairKIM::coeff(int narg, char **arg)
// Check to see if the indices range contains only integer numbers & : // Check to see if the indices range contains only integer numbers & :
if (argtostr.find_first_not_of("0123456789:") != std::string::npos) { if (argtostr.find_first_not_of("0123456789:") != std::string::npos) {
std::string msg("Illegal index_range.\n"); auto msg = fmt::format("Illegal index_range.\nExpected integer "
msg += "Expected integer parameter(s) instead of '"; "parameter(s) instead of '{}' in "
msg += argtostr; "index_range", argtostr);
msg += "' in index_range"; error->all(FLERR,msg);
error->all(FLERR, msg);
} }
std::string::size_type npos = argtostr.find(':'); std::string::size_type npos = argtostr.find(':');
if (npos != std::string::npos) { if (npos != std::string::npos) {
argtostr[npos] = ' '; argtostr[npos] = ' ';
std::stringstream str(argtostr); auto words = utils::split_words(argtostr);
str >> nlbound >> nubound; nlbound = atoi(words[0].c_str());
nubound = atoi(words[1].c_str());
if (nubound < 1 || nubound > extent || if (nubound < 1 || nubound > extent ||
nlbound < 1 || nlbound > nubound) { nlbound < 1 || nlbound > nubound) {
std::string msg("Illegal index_range '"); auto msg = fmt::format("Illegal index_range '{}-{}' for '{}' "
msg += std::to_string(nlbound) + "-" ; "parameter with the extent of '{}'",
msg += std::to_string(nubound) + "' for '"; nlbound, nubound, paramname, extent);
msg += paramname; error->all(FLERR,msg);
msg += "' parameter with the extent of '";
msg += std::to_string(extent);
msg += "'";
error->all(FLERR, msg);
} }
} else { } else {
std::stringstream str(argtostr); nlbound = atoi(argtostr.c_str());
str >> nlbound;
if (nlbound < 1 || nlbound > extent) { if (nlbound < 1 || nlbound > extent) {
std::string msg("Illegal index '"); auto msg = fmt::format("Illegal index '{}' for '{}' parameter "
msg += std::to_string(nlbound) + "' for '"; "with the extent of '{}'", nlbound,
msg += paramname; paramname, extent);
msg += "' parameter with the extent of '"; error->all(FLERR,msg);
msg += std::to_string(extent);
msg += "'";
error->all(FLERR, msg);
} }
nubound = nlbound; nubound = nlbound;
} }
} else { } else {
std::string msg = error->all(FLERR,"Wrong number of arguments for pair coefficients.\n"
"Wrong number of arguments for pair coefficients.\n"; "Index range after parameter name is mandatory");
msg += "Index range after parameter name is mandatory";
error->all(FLERR, msg);
} }
// Parameter values // Parameter values
@ -524,7 +516,7 @@ void PairKIM::coeff(int narg, char **arg)
kimerror = KIM_Model_SetParameterDouble(pkim, param_index, kimerror = KIM_Model_SetParameterDouble(pkim, param_index,
nlbound - 1 + j, V); nlbound - 1 + j, V);
if (kimerror) if (kimerror)
error->all(FLERR, "KIM SetParameterDouble returned error"); error->all(FLERR,"KIM SetParameterDouble returned error");
} }
} else if (KIM_DataType_Equal(kim_DataType, KIM_DATA_TYPE_Integer)) { } else if (KIM_DataType_Equal(kim_DataType, KIM_DATA_TYPE_Integer)) {
for (int j = 0; j < nubound - nlbound + 1; ++j) { for (int j = 0; j < nubound - nlbound + 1; ++j) {
@ -532,25 +524,22 @@ void PairKIM::coeff(int narg, char **arg)
kimerror = KIM_Model_SetParameterInteger(pkim, param_index, kimerror = KIM_Model_SetParameterInteger(pkim, param_index,
nlbound - 1 + j, V); nlbound - 1 + j, V);
if (kimerror) if (kimerror)
error->all(FLERR, "KIM SetParameterInteger returned error"); error->all(FLERR,"KIM SetParameterInteger returned error");
} }
} else } else
error->all(FLERR, "Wrong parameter type to update"); error->all(FLERR,"Wrong parameter type to update");
} else { } else {
std::string msg = auto msg = fmt::format("Wrong number of variable values for pair "
"Wrong number of variable values for pair coefficients.\n"; "coefficients.\n'{}' values are requested "
msg += "'"; "for '{}' parameter", nubound - nlbound + 1,
msg += std::to_string(nubound - nlbound + 1); paramname);
msg += "' values are requested for '"; error->all(FLERR,msg);
msg += paramname;
msg += "' parameter.";
error->all(FLERR, msg);
} }
} }
kimerror = KIM_Model_ClearThenRefresh(pkim); kimerror = KIM_Model_ClearThenRefresh(pkim);
if (kimerror) if (kimerror)
error->all(FLERR, "KIM KIM_Model_ClearThenRefresh returned error"); error->all(FLERR,"KIM KIM_Model_ClearThenRefresh returned error");
} }
} }
@ -842,11 +831,13 @@ void PairKIM::kim_init()
else if (!requestedUnitsAccepted) else if (!requestedUnitsAccepted)
error->all(FLERR,"KIM Model did not accept the requested unit system"); error->all(FLERR,"KIM Model did not accept the requested unit system");
auto logID = fmt::format("{}_Model", comm->me);
KIM_Model_SetLogID(pkim, logID.c_str());
// check that the model does not require unknown capabilities // check that the model does not require unknown capabilities
kimerror = check_for_routine_compatibility(); kimerror = check_for_routine_compatibility();
if (kimerror) if (kimerror)
error->all(FLERR, error->all(FLERR,"KIM Model requires unknown Routines. Unable to proceed");
"KIM Model requires unknown Routines. Unable to proceed");
kimerror = KIM_Model_ComputeArgumentsCreate(pkim, &pargs); kimerror = KIM_Model_ComputeArgumentsCreate(pkim, &pargs);
if (kimerror) { if (kimerror) {
@ -854,6 +845,9 @@ void PairKIM::kim_init()
error->all(FLERR,"KIM ComputeArgumentsCreate failed"); error->all(FLERR,"KIM ComputeArgumentsCreate failed");
} else kim_init_ok = true; } else kim_init_ok = true;
logID = fmt::format("{}_ComputeArguments", comm->me);
KIM_ComputeArguments_SetLogID(pargs, logID.c_str());
// determine KIM Model capabilities (used in this function below) // determine KIM Model capabilities (used in this function below)
set_kim_model_has_flags(); set_kim_model_has_flags();
@ -985,43 +979,46 @@ void PairKIM::set_lmps_flags()
error->all(FLERR,"pair_kim does not support hybrid"); error->all(FLERR,"pair_kim does not support hybrid");
// determine unit system and set lmps_units flag // determine unit system and set lmps_units flag
if ((strcmp(update->unit_style,"real")==0)) { if (strcmp(update->unit_style,"real") == 0) {
lmps_units = REAL; lmps_units = REAL;
lengthUnit = KIM_LENGTH_UNIT_A; lengthUnit = KIM_LENGTH_UNIT_A;
energyUnit = KIM_ENERGY_UNIT_kcal_mol; energyUnit = KIM_ENERGY_UNIT_kcal_mol;
chargeUnit = KIM_CHARGE_UNIT_e; chargeUnit = KIM_CHARGE_UNIT_e;
temperatureUnit = KIM_TEMPERATURE_UNIT_K; temperatureUnit = KIM_TEMPERATURE_UNIT_K;
timeUnit = KIM_TIME_UNIT_fs; timeUnit = KIM_TIME_UNIT_fs;
} else if ((strcmp(update->unit_style,"metal")==0)) { } else if (strcmp(update->unit_style,"metal") == 0) {
lmps_units = METAL; lmps_units = METAL;
lengthUnit = KIM_LENGTH_UNIT_A; lengthUnit = KIM_LENGTH_UNIT_A;
energyUnit = KIM_ENERGY_UNIT_eV; energyUnit = KIM_ENERGY_UNIT_eV;
chargeUnit = KIM_CHARGE_UNIT_e; chargeUnit = KIM_CHARGE_UNIT_e;
temperatureUnit = KIM_TEMPERATURE_UNIT_K; temperatureUnit = KIM_TEMPERATURE_UNIT_K;
timeUnit = KIM_TIME_UNIT_ps; timeUnit = KIM_TIME_UNIT_ps;
} else if ((strcmp(update->unit_style,"si")==0)) { } else if (strcmp(update->unit_style,"si") == 0) {
lmps_units = SI; lmps_units = SI;
lengthUnit = KIM_LENGTH_UNIT_m; lengthUnit = KIM_LENGTH_UNIT_m;
energyUnit = KIM_ENERGY_UNIT_J; energyUnit = KIM_ENERGY_UNIT_J;
chargeUnit = KIM_CHARGE_UNIT_C; chargeUnit = KIM_CHARGE_UNIT_C;
temperatureUnit = KIM_TEMPERATURE_UNIT_K; temperatureUnit = KIM_TEMPERATURE_UNIT_K;
timeUnit = KIM_TIME_UNIT_s; timeUnit = KIM_TIME_UNIT_s;
} else if ((strcmp(update->unit_style,"cgs")==0)) { } else if (strcmp(update->unit_style,"cgs") == 0) {
lmps_units = CGS; lmps_units = CGS;
lengthUnit = KIM_LENGTH_UNIT_cm; lengthUnit = KIM_LENGTH_UNIT_cm;
energyUnit = KIM_ENERGY_UNIT_erg; energyUnit = KIM_ENERGY_UNIT_erg;
chargeUnit = KIM_CHARGE_UNIT_statC; chargeUnit = KIM_CHARGE_UNIT_statC;
temperatureUnit = KIM_TEMPERATURE_UNIT_K; temperatureUnit = KIM_TEMPERATURE_UNIT_K;
timeUnit = KIM_TIME_UNIT_s; timeUnit = KIM_TIME_UNIT_s;
} else if ((strcmp(update->unit_style,"electron")==0)) { } else if (strcmp(update->unit_style,"electron") == 0) {
lmps_units = ELECTRON; lmps_units = ELECTRON;
lengthUnit = KIM_LENGTH_UNIT_Bohr; lengthUnit = KIM_LENGTH_UNIT_Bohr;
energyUnit = KIM_ENERGY_UNIT_Hartree; energyUnit = KIM_ENERGY_UNIT_Hartree;
chargeUnit = KIM_CHARGE_UNIT_e; chargeUnit = KIM_CHARGE_UNIT_e;
temperatureUnit = KIM_TEMPERATURE_UNIT_K; temperatureUnit = KIM_TEMPERATURE_UNIT_K;
timeUnit = KIM_TIME_UNIT_fs; timeUnit = KIM_TIME_UNIT_fs;
} else if ((strcmp(update->unit_style,"lj")==0)) { } else if (strcmp(update->unit_style,"lj") == 0 ||
error->all(FLERR,"LAMMPS unit_style lj not supported by KIM models"); strcmp(update->unit_style,"micro") == 0 ||
strcmp(update->unit_style,"nano") == 0) {
error->all(FLERR,fmt::format("LAMMPS unit_style {} not supported "
"by KIM models", update->unit_style));
} else { } else {
error->all(FLERR,"Unknown unit_style"); error->all(FLERR,"Unknown unit_style");
} }
@ -1102,29 +1099,33 @@ void PairKIM::set_kim_model_has_flags()
KIM_SUPPORT_STATUS_required)) { KIM_SUPPORT_STATUS_required)) {
std::string msg("KIM Model requires unsupported compute argument: "); std::string msg("KIM Model requires unsupported compute argument: ");
msg += KIM_ComputeArgumentName_ToString(computeArgumentName); msg += KIM_ComputeArgumentName_ToString(computeArgumentName);
error->all(FLERR, msg); error->all(FLERR,msg);
} }
} }
if (comm->me == 0) {
if (KIM_SupportStatus_Equal(kim_model_support_for_energy, if (KIM_SupportStatus_Equal(kim_model_support_for_energy,
KIM_SUPPORT_STATUS_notSupported)) KIM_SUPPORT_STATUS_notSupported))
error->warning(FLERR,"KIM Model does not provide `partialEnergy'; " error->warning(FLERR,"KIM Model does not provide 'partialEnergy'; "
"Potential energy will be zero"); "Potential energy will be zero");
if (KIM_SupportStatus_Equal(kim_model_support_for_forces, if (KIM_SupportStatus_Equal(kim_model_support_for_forces,
KIM_SUPPORT_STATUS_notSupported)) KIM_SUPPORT_STATUS_notSupported))
error->warning(FLERR,"KIM Model does not provide `partialForce'; " error->warning(FLERR,"KIM Model does not provide 'partialForce'; "
"Forces will be zero"); "Forces will be zero");
if (KIM_SupportStatus_Equal(kim_model_support_for_particleEnergy, if (KIM_SupportStatus_Equal(kim_model_support_for_particleEnergy,
KIM_SUPPORT_STATUS_notSupported)) KIM_SUPPORT_STATUS_notSupported))
error->warning(FLERR,"KIM Model does not provide `partialParticleEnergy'; " error->warning(FLERR,"KIM Model does not provide "
"'partialParticleEnergy'; "
"energy per atom will be zero"); "energy per atom will be zero");
if (KIM_SupportStatus_Equal(kim_model_support_for_particleVirial, if (KIM_SupportStatus_Equal(kim_model_support_for_particleVirial,
KIM_SUPPORT_STATUS_notSupported)) KIM_SUPPORT_STATUS_notSupported))
error->warning(FLERR,"KIM Model does not provide `partialParticleVirial'; " error->warning(FLERR,"KIM Model does not provide "
"'partialParticleVirial'; "
"virial per atom will be zero"); "virial per atom will be zero");
}
int numberOfComputeCallbackNames; int numberOfComputeCallbackNames;
KIM_COMPUTE_CALLBACK_NAME_GetNumberOfComputeCallbackNames( KIM_COMPUTE_CALLBACK_NAME_GetNumberOfComputeCallbackNames(

View File

@ -17,6 +17,7 @@
#include "lammps.h" #include "lammps.h"
#include "lmppython.h" #include "lmppython.h"
#include "modify.h" #include "modify.h"
#include "output.h"
#include "utils.h" #include "utils.h"
#include "variable.h" #include "variable.h"
#include "gmock/gmock.h" #include "gmock/gmock.h"
@ -82,17 +83,24 @@ TEST_F(KimCommandsTest, kim_init)
{ {
if (!LAMMPS::is_installed_pkg("KIM")) GTEST_SKIP(); if (!LAMMPS::is_installed_pkg("KIM")) GTEST_SKIP();
TEST_FAILURE(".*ERROR: Illegal kim_init command.*", lmp->input->one("kim_init");); TEST_FAILURE(".*ERROR: Illegal kim_init command.*",
lmp->input->one("kim_init"););
TEST_FAILURE(".*ERROR: Illegal kim_init command.*", TEST_FAILURE(".*ERROR: Illegal kim_init command.*",
lmp->input->one("kim_init LennardJones_Ar real si");); lmp->input->one("kim_init LennardJones_Ar real si"););
TEST_FAILURE(".*ERROR: LAMMPS unit_style lj not supported by KIM models.*", TEST_FAILURE(".*ERROR: LAMMPS unit_style lj not supported by KIM models.*",
lmp->input->one("kim_init LennardJones_Ar lj");); lmp->input->one("kim_init LennardJones_Ar lj"););
TEST_FAILURE(".*ERROR: LAMMPS unit_style micro not supported by KIM models.*",
lmp->input->one("kim_init LennardJones_Ar micro"););
TEST_FAILURE(".*ERROR: LAMMPS unit_style nano not supported by KIM models.*",
lmp->input->one("kim_init LennardJones_Ar nano"););
TEST_FAILURE(".*ERROR: Unknown unit_style.*", TEST_FAILURE(".*ERROR: Unknown unit_style.*",
lmp->input->one("kim_init LennardJones_Ar new_style");); lmp->input->one("kim_init LennardJones_Ar new_style"););
TEST_FAILURE(".*ERROR: KIM Model name not found.*", TEST_FAILURE(".*ERROR: KIM Model name not found.*",
lmp->input->one("kim_init Unknown_Model real");); lmp->input->one("kim_init Unknown_Model real"););
TEST_FAILURE(".*ERROR: Incompatible units for KIM Simulator Model, required units = metal.*", TEST_FAILURE(".*ERROR: Incompatible units for KIM Simulator Model, required units = metal.*",
lmp->input->one("kim_init Sim_LAMMPS_LJcut_AkersonElliott_Alchemy_PbAu real");); lmp->input->one("kim_init Sim_LAMMPS_LJcut_AkersonElliott_Alchemy_PbAu real"););
// TEST_FAILURE(".*ERROR: KIM Model does not support the requested unit system.*",
// lmp->input->one("kim_init ex_model_Ar_P_Morse real"););
if (!verbose) ::testing::internal::CaptureStdout(); if (!verbose) ::testing::internal::CaptureStdout();
lmp->input->one("kim_init LennardJones_Ar real"); lmp->input->one("kim_init LennardJones_Ar real");
@ -125,6 +133,17 @@ TEST_F(KimCommandsTest, kim_interactions)
lmp->input->one("create_atoms 1 box"); lmp->input->one("create_atoms 1 box");
if (!verbose) ::testing::internal::GetCapturedStdout(); if (!verbose) ::testing::internal::GetCapturedStdout();
TEST_FAILURE(".*ERROR: Illegal kim_interactions command.*",
lmp->input->one("kim_interactions Ar Ar"););
if (!verbose) ::testing::internal::CaptureStdout();
lmp->input->one("clear");
lmp->input->one("lattice fcc 4.4300");
lmp->input->one("region box block 0 20 0 20 0 20");
lmp->input->one("create_box 4 box");
lmp->input->one("create_atoms 4 box");
if (!verbose) ::testing::internal::GetCapturedStdout();
TEST_FAILURE(".*ERROR: Illegal kim_interactions command.*", TEST_FAILURE(".*ERROR: Illegal kim_interactions command.*",
lmp->input->one("kim_interactions Ar Ar");); lmp->input->one("kim_interactions Ar Ar"););
@ -172,6 +191,21 @@ TEST_F(KimCommandsTest, kim_interactions)
TEST_FAILURE(".*ERROR: Species 'Ar' is not supported by this KIM Simulator Model.*", TEST_FAILURE(".*ERROR: Species 'Ar' is not supported by this KIM Simulator Model.*",
lmp->input->one("kim_interactions Ar");); lmp->input->one("kim_interactions Ar"););
if (!verbose) ::testing::internal::CaptureStdout();
lmp->input->one("clear");
lmp->input->one("kim_init Sim_LAMMPS_LJcut_AkersonElliott_Alchemy_PbAu metal");
lmp->input->one("lattice fcc 4.08");
lmp->input->one("region box block 0 10 0 10 0 10");
lmp->input->one("create_box 1 box");
lmp->input->one("create_atoms 1 box");
lmp->input->one("kim_interactions Au");
if (!verbose) ::testing::internal::GetCapturedStdout();
// ASSERT_EQ(lmp->output->var_kim_periodic, 1);
// TEST_FAILURE(".*ERROR: Incompatible units for KIM Simulator Model.*",
// lmp->input->one("kim_interactions Au"););
if (!verbose) ::testing::internal::CaptureStdout(); if (!verbose) ::testing::internal::CaptureStdout();
lmp->input->one("clear"); lmp->input->one("clear");
lmp->input->one("kim_init LennardJones_Ar real"); lmp->input->one("kim_init LennardJones_Ar real");
@ -302,6 +336,133 @@ TEST_F(KimCommandsTest, kim_property)
} }
} }
TEST_F(KimCommandsTest, kim_query)
{
if (!LAMMPS::is_installed_pkg("KIM")) GTEST_SKIP();
TEST_FAILURE(".*ERROR: Illegal kim_query command.*",
lmp->input->one("kim_query"););
TEST_FAILURE(".*ERROR: Must use 'kim_init' before 'kim_query'.*",
lmp->input->one("kim_query a0 get_lattice_constant_cubic"););
if (!verbose) ::testing::internal::CaptureStdout();
lmp->input->one("clear");
lmp->input->one("kim_init LennardJones612_UniversalShifted__MO_959249795837_003 real");
if (!verbose) ::testing::internal::GetCapturedStdout();
TEST_FAILURE(".*ERROR: Illegal kim_query command.\nThe keyword 'split' "
"must be followed by the name of the query function.*",
lmp->input->one("kim_query a0 split"););
TEST_FAILURE(".*ERROR: Illegal kim_query command.\nThe 'list' keyword "
"can not be used after 'split'.*",
lmp->input->one("kim_query a0 split list"););
TEST_FAILURE(".*ERROR: Illegal kim_query command.\nThe 'list' keyword "
"must be followed by \\('split' and\\) the name of the query "
"function.*", lmp->input->one("kim_query a0 list"););
TEST_FAILURE(".*ERROR: Illegal 'model' key in kim_query command.*",
lmp->input->one("kim_query a0 get_lattice_constant_cubic "
"model=[MO_959249795837_003]"););
TEST_FAILURE(".*ERROR: Illegal query format.\nInput argument of `crystal` "
"to kim_query is wrong. The query format is the "
"keyword=\\[value\\], where value is always an array of one "
"or more comma-separated items.*",
lmp->input->one("kim_query a0 get_lattice_constant_cubic "
"crystal"););
TEST_FAILURE(".*ERROR: Illegal query format.\nInput argument of `"
"crystal=fcc` to kim_query is wrong. The query format is the "
"keyword=\\[value\\], where value is always an array of one "
"or more comma-separated items.*",
lmp->input->one("kim_query a0 get_lattice_constant_cubic "
"crystal=fcc"););
TEST_FAILURE(".*ERROR: Illegal query format.\nInput argument of `"
"crystal=\\[fcc` to kim_query is wrong. The query format is "
"the keyword=\\[value\\], where value is always an array of "
"one or more comma-separated items.*",
lmp->input->one("kim_query a0 get_lattice_constant_cubic "
"crystal=[fcc"););
TEST_FAILURE(".*ERROR: Illegal query format.\nInput argument of `"
"crystal=fcc\\]` to kim_query is wrong. The query format is "
"the keyword=\\[value\\], where value is always an array of "
"one or more comma-separated items.*",
lmp->input->one("kim_query a0 get_lattice_constant_cubic "
"crystal=fcc]"););
std::string squery("kim_query a0 get_lattice_constant_cubic ");
squery += "crystal=[\"fcc\"] species=\"Al\",\"Ni\" units=[\"angstrom\"]";
TEST_FAILURE(".*ERROR: Illegal query format.\nInput argument of `species="
"\"Al\",\"Ni\"` to kim_query is wrong. The query format is "
"the keyword=\\[value\\], where value is always an array of "
"one or more comma-separated items.*",
lmp->input->one(squery););
squery = "kim_query a0 get_lattice_constant_cubic ";
squery += "crystal=[\"fcc\"] species=\"Al\",\"Ni\", units=[\"angstrom\"]";
TEST_FAILURE(".*ERROR: Illegal query format.\nInput argument of `species="
"\"Al\",\"Ni\",` to kim_query is wrong. The query format is "
"the keyword=\\[value\\], where value is always an array of "
"one or more comma-separated items.*",
lmp->input->one(squery););
squery = "kim_query a0 get_lattice_constant_cubic crystal=[fcc] "
"species=[Al]";
TEST_FAILURE(".*ERROR: OpenKIM query failed:.*", lmp->input->one(squery););
squery = "kim_query a0 get_lattice_constant_cubic crystal=[fcc] "
"units=[\"angstrom\"]";
TEST_FAILURE(".*ERROR: OpenKIM query failed:.*", lmp->input->one(squery););
// if (!verbose) ::testing::internal::CaptureStdout();
// lmp->input->one("clear");
// lmp->input->one("kim_init EAM_Dynamo_Mendelev_2007_Zr__MO_848899341753_000 metal");
// squery = "kim_query latconst split get_lattice_constant_hexagonal ";
// squery += "crystal=[\"hcp\"] species=[\"Zr\"] units=[\"angstrom\"]";
// lmp->input->one(squery);
// if (!verbose) ::testing::internal::GetCapturedStdout();
// ASSERT_TRUE((std::string(lmp->input->variable->retrieve("latconst_1")) ==
// std::string("3.234055244384789")));
// ASSERT_TRUE((std::string(lmp->input->variable->retrieve("latconst_2")) ==
// std::string("5.167650199630013")));
// if (!verbose) ::testing::internal::CaptureStdout();
// lmp->input->one("clear");
// lmp->input->one("kim_init EAM_Dynamo_Mendelev_2007_Zr__MO_848899341753_000 metal");
// squery = "kim_query latconst list get_lattice_constant_hexagonal ";
// squery += "crystal=[hcp] species=[Zr] units=[angstrom]";
// lmp->input->one(squery);
// if (!verbose) ::testing::internal::GetCapturedStdout();
// ASSERT_TRUE((std::string(lmp->input->variable->retrieve("latconst")) ==
// std::string("3.234055244384789 5.167650199630013")));
// squery = "kim_query latconst list get_lattice_constant_hexagonal ";
// squery += "crystal=[bcc] species=[Zr] units=[angstrom]";
// TEST_FAILURE(".*ERROR: OpenKIM query failed:.*", lmp->input->one(squery););
// if (!verbose) ::testing::internal::CaptureStdout();
// lmp->input->one("clear");
// lmp->input->one("kim_init EAM_Dynamo_ErcolessiAdams_1994_Al__MO_123629422045_005 metal");
// squery = "kim_query alpha get_linear_thermal_expansion_coefficient_cubic ";
// squery += "crystal=[fcc] species=[Al] units=[1/K] temperature=[293.15] ";
// squery += "temperature_units=[K]";
// lmp->input->one(squery);
// if (!verbose) ::testing::internal::GetCapturedStdout();
// ASSERT_TRUE((std::string(lmp->input->variable->retrieve("alpha")) ==
// std::string("1.654960564704273e-05")));
}
} // namespace LAMMPS_NS } // namespace LAMMPS_NS
int main(int argc, char **argv) int main(int argc, char **argv)