Unverified Commit 24a0933e authored by Richard Berger's avatar Richard Berger
Browse files

Refactor PotentialFileReader

parent 60f17e73
Loading
Loading
Loading
Loading
+75 −65
Original line number Diff line number Diff line
@@ -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
  try {
    return reader->next_line(nparams);
  } catch (FileReaderException & e) {
    error->one(FLERR, e.what());
  }
  return nullptr;
}

  // strip comment
  if ((ptr = strchr(line, '#'))) *ptr = '\0';

  nwords = utils::count_words(line);

  if (nwords > 0) {
    n = strlen(line);
void PotentialFileReader::next_dvector(int n, double * list) {
  try {
    return reader->next_dvector(n, list);
  } catch (FileReaderException & e) {
    error->one(FLERR, e.what());
  }
}

  while(nwords == 0 || nwords < nparams) {
    char *ptr = fgets(&line[n], MAXLINE - n, fp);
/* ----------------------------------------------------------------------
   open a potential file as specified by name
   if fails, search in dir specified by env variable LAMMPS_POTENTIALS
------------------------------------------------------------------------- */

    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);
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;
    }


    // strip comment
    if ((ptr = strchr(line, '#'))) *ptr = '\0';

    nwords = utils::count_words(line);

    // skip line if blank
    if (nwords > 0) {
      n = strlen(line);
  }

  if(!date.empty()) {
    utils::logmesg(lmp, fmt::format("Reading potential file {} with DATE: {}", filename, date));
  }

  return line;
  return new TextFileReader(filepath, potential_name + " potential");
}

void PotentialFileReader::next_dvector(int n, double * list) {
  int i = 0;
  while (i < n) {
    char *ptr = fgets(line, MAXLINE, fp);
/* ----------------------------------------------------------------------
   read first line of potential file
   if has DATE field, print following word
------------------------------------------------------------------------- */

    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);
      }
    }
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()) {
      list[i++] = values.next_double();
      std::string word = values.next_string();
      if (word == "DATE:") {
        if (values.has_next()) {
          std::string date = values.next_string();
          return date;
        }
      }
    }
  }
  return "";
}
+6 −4
Original line number Diff line number Diff line
@@ -21,15 +21,17 @@
#include <string>

#include "pointers.h"
#include "text_file_reader.h"

namespace LAMMPS_NS
{
  class PotentialFileReader : protected Pointers {
    std::string potential_name;
    TextFileReader * reader;
    std::string filename;
    static const int MAXLINE = 1024;
    char line[MAXLINE];
    FILE *fp;
    std::string potential_name;

    TextFileReader * open_potential(const std::string& path);
    std::string get_potential_date(const std::string & path);

  public:
    PotentialFileReader(class LAMMPS *lmp, const std::string &filename, const std::string &potential_name);
+117 −0
Original line number Diff line number Diff line
/* -*- c++ -*- ----------------------------------------------------------
   LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
   http://lammps.sandia.gov, Sandia National Laboratories
   Steve Plimpton, sjplimp@sandia.gov

   Copyright (2003) Sandia Corporation.  Under the terms of Contract
   DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
   certain rights in this software.  This software is distributed under
   the GNU General Public License.

   See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */

/* ----------------------------------------------------------------------
   Contributing authors: Richard Berger (Temple U)
------------------------------------------------------------------------- */

#include "lammps.h"
#include "force.h"
#include "error.h"
#include "comm.h"
#include "utils.h"
#include "text_file_reader.h"
#include "tokenizer.h"
#include "fmt/format.h"

#include <cstring>

using namespace LAMMPS_NS;

TextFileReader::TextFileReader(const std::string &filename, const std::string &filetype) 
  : filename(filename), filetype(filetype)
{
  fp = fopen(filename.c_str(), "r");

  if (fp == nullptr) {
    throw FileReaderException(fmt::format("cannot open {} file {}", filetype, filename));
  }
}

TextFileReader::~TextFileReader() {
  fclose(fp);
}

void TextFileReader::skip_line() {
  char *ptr = fgets(line, MAXLINE, fp);
  if (ptr == nullptr) {
    // EOF
    throw EOFException(fmt::format("Missing line in {} file!", filetype));
  }
}

char *TextFileReader::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;
  }

  // strip comment
  if (ignore_comments && (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) {
        throw EOFException(fmt::format("Incorrect format in {} file! {}/{} parameters", filetype.c_str(), nwords, nparams));
      }
      return nullptr;
    }


    // strip comment
    if (ignore_comments && (ptr = strchr(line, '#'))) *ptr = '\0';

    nwords = utils::count_words(line);

    // skip line if blank
    if (nwords > 0) {
      n = strlen(line);
    }
  }

  return line;
}

void TextFileReader::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) {
        throw FileReaderException(fmt::format("Incorrect format in {} file! {}/{} values", filetype, i, n));
      }
    }

    ValueTokenizer values(line);
    while(values.has_next()) {
      list[i++] = values.next_double();
    }
  }
}

src/text_file_reader.h

0 → 100644
+68 −0
Original line number Diff line number Diff line
/* -*- c++ -*- ----------------------------------------------------------
   LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
   http://lammps.sandia.gov, Sandia National Laboratories
   Steve Plimpton, sjplimp@sandia.gov

   Copyright (2003) Sandia Corporation.  Under the terms of Contract
   DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
   certain rights in this software.  This software is distributed under
   the GNU General Public License.

   See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */

/* ----------------------------------------------------------------------
   Contributing authors: Richard Berger (Temple U)
------------------------------------------------------------------------- */

#ifndef LMP_TEXT_FILE_READER_H
#define LMP_TEXT_FILE_READER_H

#include <cstdio>
#include <string>
#include <exception>

namespace LAMMPS_NS
{
  class TextFileReader {
    std::string filename;
    std::string filetype;
    static const int MAXLINE = 1024;
    char line[MAXLINE];
    FILE *fp;

  public:
    bool ignore_comments;
    
    TextFileReader(const std::string &filename, const std::string &filetype);
    ~TextFileReader();

    void skip_line();
    char * next_line(int nparams = 0);

    void next_dvector(int n, double * list);
  };

  class FileReaderException : public std::exception {
    std::string message;
  public:
    FileReaderException(const std::string & msg) : message(msg) {
    }
  
    ~FileReaderException() throw() {
    }
  
    virtual const char * what() const throw() {
      return message.c_str();
    }
  };

  class EOFException : public FileReaderException {
  public:
    EOFException(const std::string & msg) : FileReaderException(msg) {
    }
  };

} // namespace LAMMPS_NS

#endif