Refactor PotentialFileReader

This commit is contained in:
Richard Berger
2020-06-02 14:18:11 -04:00
parent 60f17e7397
commit 24a0933e2a
4 changed files with 278 additions and 81 deletions

View File

@ -22,6 +22,7 @@
#include "potential_file_reader.h"
#include "utils.h"
#include "tokenizer.h"
#include "fmt/format.h"
#include <cstring>
@ -30,102 +31,111 @@ using namespace LAMMPS_NS;
PotentialFileReader::PotentialFileReader(LAMMPS *lmp,
const std::string &filename,
const std::string &potential_name) :
Pointers(lmp), filename(filename), potential_name(potential_name)
Pointers(lmp),
reader(nullptr),
filename(filename),
potential_name(potential_name)
{
if (comm->me != 0) {
error->one(FLERR, "PotentialFileReader should only be called by proc 0!");
}
fp = force->open_potential(filename.c_str());
if (fp == NULL) {
char str[128];
snprintf(str, 128, "cannot open %s potential file %s", potential_name.c_str(), filename.c_str());
error->one(FLERR, str);
try {
reader = open_potential(filename);
} catch (FileReaderException & e) {
error->one(FLERR, e.what());
}
}
PotentialFileReader::~PotentialFileReader() {
fclose(fp);
delete reader;
}
void PotentialFileReader::skip_line() {
char *ptr = fgets(line, MAXLINE, fp);
if (ptr == nullptr) {
// EOF
char str[128];
snprintf(str, 128, "Missing line in %s potential file!", potential_name.c_str());
error->one(FLERR, str);
try {
reader->skip_line();
} catch (FileReaderException & e) {
error->one(FLERR, e.what());
}
}
char *PotentialFileReader::next_line(int nparams) {
// concatenate lines until have nparams words
int n = 0;
int nwords = 0;
char *ptr = fgets(line, MAXLINE, fp);
if (ptr == nullptr) {
// EOF
return nullptr;
try {
return reader->next_line(nparams);
} catch (FileReaderException & e) {
error->one(FLERR, e.what());
}
// strip comment
if ((ptr = strchr(line, '#'))) *ptr = '\0';
nwords = utils::count_words(line);
if (nwords > 0) {
n = strlen(line);
}
while(nwords == 0 || nwords < nparams) {
char *ptr = fgets(&line[n], MAXLINE - n, fp);
if (ptr == nullptr) {
// EOF
if (nwords > 0 && nwords < nparams) {
char str[128];
snprintf(str, 128, "Incorrect format in %s potential file! %d/%d parameters", potential_name.c_str(), nwords, nparams);
error->one(FLERR, str);
}
return nullptr;
}
// strip comment
if ((ptr = strchr(line, '#'))) *ptr = '\0';
nwords = utils::count_words(line);
// skip line if blank
if (nwords > 0) {
n = strlen(line);
}
}
return line;
return nullptr;
}
void PotentialFileReader::next_dvector(int n, double * list) {
int i = 0;
while (i < n) {
char *ptr = fgets(line, MAXLINE, fp);
if (ptr == nullptr) {
// EOF
if (i < n) {
char str[128];
snprintf(str, 128, "Incorrect format in %s potential file! %d/%d values", potential_name.c_str(), i, n);
error->one(FLERR, str);
}
}
ValueTokenizer values(line);
while(values.has_next()) {
list[i++] = values.next_double();
}
try {
return reader->next_dvector(n, list);
} catch (FileReaderException & e) {
error->one(FLERR, e.what());
}
}
/* ----------------------------------------------------------------------
open a potential file as specified by name
if fails, search in dir specified by env variable LAMMPS_POTENTIALS
------------------------------------------------------------------------- */
TextFileReader * PotentialFileReader::open_potential(const std::string& path) {
// attempt to open file directly
// if successful, return filename
std::string filepath = path;
std::string filename = utils::path_basename(path);
std::string date;
if(utils::file_is_readable(filepath)) {
date = get_potential_date(filepath);
} else {
// try the environment variable directory
const char *path = getenv("LAMMPS_POTENTIALS");
if (path != nullptr){
std::string pot = utils::path_basename(filepath);
filepath = utils::path_join(path, pot);
if (utils::file_is_readable(filepath)) {
date = get_potential_date(filepath);
} else {
return nullptr;
}
} else {
return nullptr;
}
}
if(!date.empty()) {
utils::logmesg(lmp, fmt::format("Reading potential file {} with DATE: {}", filename, date));
}
return new TextFileReader(filepath, potential_name + " potential");
}
/* ----------------------------------------------------------------------
read first line of potential file
if has DATE field, print following word
------------------------------------------------------------------------- */
std::string PotentialFileReader::get_potential_date(const std::string & path) {
TextFileReader reader(path, potential_name + " potential");
reader.ignore_comments = false;
char * line = nullptr;
while (line = reader.next_line()) {
ValueTokenizer values(line);
while (values.has_next()) {
std::string word = values.next_string();
if (word == "DATE:") {
if (values.has_next()) {
std::string date = values.next_string();
return date;
}
}
}
}
return "";
}