4.8. Utility functions
The utils
sub-namespace inside the LAMMPS_NS
namespace provides
a collection of convenience functions and utilities that perform common
tasks that are required repeatedly throughout the LAMMPS code like
reading or writing to files with error checking or translation of
strings into specific types of numbers with checking for validity. This
reduces redundant implementations and encourages consistent behavior.
4.8.1. I/O with status check
These are wrappers around the corresponding C library calls like
fgets()
or fread()
. They will check if there were errors
on reading or an unexpected end-of-file state was reached. In that
case, the functions will stop the calculation with an error message,
indicating the name of the problematic file, if possible.
-
void
LAMMPS_NS::utils
::
sfgets
(const char *srcname, int srcline, char *s, int size, FILE *fp, const char *filename, Error *error) safe wrapper around fgets() which aborts on errors or EOF and prints a suitable error message to help debugging
- Parameters
srcname
: name of the calling source file (from FLERR macro)srcline
: line in the calling source file (from FLERR macro)s
: buffer for storing the result of fgets()size
: size of buffer s (max number of bytes read by fgets())fp
: file pointer used by fgets()filename
: file name associated with fp (may be a null pointer; then LAMMPS will try to detect)error
: pointer to Error class instance (for abort)
-
void
LAMMPS_NS::utils
::
sfread
(const char *srcname, int srcline, void *s, size_t size, size_t num, FILE *fp, const char *filename, Error *error) safe wrapper around fread() which aborts on errors or EOF and prints a suitable error message to help debugging
- Parameters
srcname
: name of the calling source file (from FLERR macro)srcline
: line in the calling source file (from FLERR macro)s
: buffer for storing the result of fread()size
: size of data elements read by fread()num
: number of data elements read by fread()fp
: file pointer used by fread()filename
: file name associated with fp (may be a null pointer; then LAMMPS will try to detect)error
: pointer to Error class instance (for abort)
4.8.2. String to number conversions with validity check
These functions should be used to convert strings to numbers. They are
are strongly preferred over C library calls like atoi()
or
atof()
since they check if the entire provided string is a valid
(floating-point or integer) number, and will error out instead of
silently returning the result of a partial conversion or zero in cases
where the string is not a valid number. This behavior allows to more
easily detect typos or issues when processing input files.
The do_abort flag should be set to true
in case this function
is called only on a single MPI rank, as that will then trigger the
a call to Error::one()
for errors instead of Error::all()
and avoids a “hanging” calculation when run in parallel.
Please also see is_integer()
and is_double()
for testing
strings for compliance without conversion.
-
double
LAMMPS_NS::utils
::
numeric
(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) Convert a string to a floating point number while checking if it is a valid floating point or integer number
- Return
double precision floating point number
- Parameters
file
: name of source file for error messageline
: line number in source file for error messagestr
: string to be converted to numberdo_abort
: determines whether to call Error::one() or Error::all()lmp
: pointer to top-level LAMMPS class instance
-
int
LAMMPS_NS::utils
::
inumeric
(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) Convert a string to an integer number while checking if it is a valid integer number (regular int)
- Return
integer number (regular int)
- Parameters
file
: name of source file for error messageline
: line number in source file for error messagestr
: string to be converted to numberdo_abort
: determines whether to call Error::one() or Error::all()lmp
: pointer to top-level LAMMPS class instance
-
bigint
LAMMPS_NS::utils
::
bnumeric
(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) Convert a string to an integer number while checking if it is a valid integer number (bigint)
- Return
integer number (bigint)
- Parameters
file
: name of source file for error messageline
: line number in source file for error messagestr
: string to be converted to numberdo_abort
: determines whether to call Error::one() or Error::all()lmp
: pointer to top-level LAMMPS class instance
-
tagint
LAMMPS_NS::utils
::
tnumeric
(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) Convert a string to an integer number while checking if it is a valid integer number (tagint)
- Return
integer number (tagint)
- Parameters
file
: name of source file for error messageline
: line number in source file for error messagestr
: string to be converted to numberdo_abort
: determines whether to call Error::one() or Error::all()lmp
: pointer to top-level LAMMPS class instance
4.8.3. String processing
The following are functions to help with processing strings and parsing files or arguments.
-
std::string
LAMMPS_NS::utils
::
trim
(const std::string &line) Trim leading and trailing whitespace. Like TRIM() in Fortran.
- Return
new string without whitespace (string)
- Parameters
line
: string that should be trimmed
-
std::string
LAMMPS_NS::utils
::
trim_comment
(const std::string &line) Return string with anything from ‘#’ onward removed
- Return
new string without comment (string)
- Parameters
line
: string that should be trimmed
-
size_t
LAMMPS_NS::utils
::
count_words
(const char *text) Count words in C-string, ignore any whitespace matching ” \t\r\n\f”
- Return
number of words found
- Parameters
text
: string that should be searched
-
size_t
LAMMPS_NS::utils
::
count_words
(const std::string &text) Count words in string, ignore any whitespace matching ” \t\r\n\f”
- Return
number of words found
- Parameters
text
: string that should be searched
-
size_t
LAMMPS_NS::utils
::
count_words
(const std::string &text, const std::string &separators) Count words in string with custom choice of separating characters
- Return
number of words found
- Parameters
text
: string that should be searchedseparators
: string containing characters that will be treated as whitespace
-
size_t
LAMMPS_NS::utils
::
trim_and_count_words
(const std::string &text, const std::string &separators = " \t\r\n\f") Count words in a single line, trim anything from ‘#’ onward
- Return
number of words found
- Parameters
text
: string that should be trimmed and searchedseparators
: string containing characters that will be treated as whitespace
-
std::vector<std::string>
LAMMPS_NS::utils
::
split_words
(const std::string &text) Take text and split into non-whitespace words.
This can handle strings with single and double quotes, escaped quotes, and escaped codes within quotes, but due to using an STL container and STL strings is rather slow because of making copies. Designed for parsing command lines and similar text and not for time critical processing. Use a tokenizer class for that.
- See also
\param text string that should be split \return STL vector with the words
-
bool
LAMMPS_NS::utils
::
strmatch
(const std::string &text, const std::string &pattern) Match text against a simplified regex pattern
More flexible and specific matching of a string against a pattern. This function is supposed to be a more safe, more specific and simple to use API to find pattern matches. The purpose is to replace uses of either strncmp() or strstr() in the code base to find sub-strings safely. With strncmp() finding prefixes, the number of characters to match must be counted, which can lead to errors, while using “^pattern” will do the same with less problems. Matching for suffixes using strstr() is not as specific as ‘pattern$’, and complex matches, e.g. “^rigid.*\/small.*”, to match all small body optimized rigid fixes require only one test.
- Return
true if the pattern matches, false if not
- Parameters
text
: the text to be matched against the patternpattern
: the search pattern, which may contain regexp markers
The use of std::string arguments allows for simple concatenation even with char * type variables. Example: utils::strmatch(text, std::string(“^”) + charptr)
-
bool
LAMMPS_NS::utils
::
is_integer
(const std::string &str) Check if string can be converted to valid integer
- Return
true, if string contains valid a integer, false otherwise
- Parameters
str
: string that should be checked
-
bool
LAMMPS_NS::utils
::
is_double
(const std::string &str) Check if string can be converted to valid floating-point number
- Return
true, if string contains valid number, false otherwise
- Parameters
str
: string that should be checked
4.8.4. File and path functions
-
const char *
LAMMPS_NS::utils
::
guesspath
(char *buf, int len, FILE *fp) Try to detect pathname from FILE pointer.
Currently only supported on Linux, otherwise will report “(unknown)”.
On Linux the folder /proc/self/fd holds symbolic links to the actual pathnames associated with each open file descriptor of the current process.
- Return
pointer to the storage buffer, i.e. buf
- Parameters
buf
: storage buffer for pathname. output will be truncated if not large enoughlen
: size of storage buffer. output will be truncated to this length - 1fp
: FILE pointer struct from STDIO library for which we want to detect the name
This function is used to provide a filename with error messages in functions where the filename is not passed as an argument, but the FILE * pointer.
-
std::string
LAMMPS_NS::utils
::
path_basename
(const std::string &path) Strip off leading part of path, return just the filename
- Return
file name
- Parameters
path
: file path
-
std::string
LAMMPS_NS::utils
::
path_join
(const std::string &a, const std::string &b) Join two pathname segments
This uses the forward slash ‘/’ character unless LAMMPS is compiled for Windows where it used the equivalent backward slash ‘'.
- Return
combined path
- Parameters
a
: first pathb
: second path
-
bool
LAMMPS_NS::utils
::
file_is_readable
(const std::string &path) Check if file exists and is readable
- Return
true if file exists and is readable
- Parameters
path
: file path
4.8.5. Potential file functions
-
std::string
LAMMPS_NS::utils
::
get_potential_file_path
(const std::string &path) Determine full path of potential file. If file is not found in current directory, search directories listed in LAMMPS_POTENTIALS environment variable
- Return
full path to potential file
- Parameters
path
: file path
-
std::string
LAMMPS_NS::utils
::
get_potential_date
(const std::string &path, const std::string &potential_name) Read potential file and return DATE field if it is present
- Return
DATE field if present
- Parameters
path
: file pathpotential_name
: name of potential that is being read
-
std::string
LAMMPS_NS::utils
::
get_potential_units
(const std::string &path, const std::string &potential_name) Read potential file and return UNITS field if it is present
- Return
UNITS field if present
- Parameters
path
: file pathpotential_name
: name of potential that is being read
-
int
LAMMPS_NS::utils
::
get_supported_conversions
(const int property) Return bitmask of available conversion factors for a given property
- Return
bitmask indicating available conversions
- Parameters
property
: property to be converted
-
double
LAMMPS_NS::utils
::
get_conversion_factor
(const int property, const int conversion) Return unit conversion factor for given property and selected from/to units
- Return
conversion factor
- Parameters
property
: property to be convertedconversion
: constant indicating the conversion
-
FILE *
LAMMPS_NS::utils
::
open_potential
(const std::string &name, LAMMPS *lmp, int *auto_convert) Open a potential file as specified by name
If opening the file directly fails, the function will search for it in the list of folder pointed to by the environment variable
LAMMPS_POTENTIALS
(if it is set).If the potential file has a
UNITS
tag in the first line, the tag’s value is compared to the current unit style setting. The behavior of the function then depends on the value of the auto_convert parameter. If it is a null pointer, then the unit values must match or else the open will fail with an error. Otherwise the bitmask that auto_convert points to is used check for compatibility with possible automatic conversions by the calling function. If compatible, the bitmask is set to the required conversion orutils::NOCONVERT
.- Return
FILE pointer of the opened potential file or
nullptr
- Parameters
name
: file- or pathname of the potential filelmp
: pointer to top-level LAMMPS class instanceauto_convert
: pointer to unit conversion bitmask ornullptr
4.8.6. Argument processing
-
template<typename
TYPE
>
voidLAMMPS_NS::utils
::
bounds
(const char *file, int line, const std::string &str, bigint nmin, bigint nmax, TYPE &nlo, TYPE &nhi, Error *error) Compute index bounds derived from a string with a possible wildcard
This functions processes the string in str and set the values of nlo and nhi according to the following five cases:
a single number, i: nlo = i; nhi = i;
a single asterisk, *: nlo = nmin; nhi = nmax;
a single number followed by an asterisk, i*: nlo = i; nhi = nmax;
a single asterisk followed by a number, *i: nlo = nmin; nhi = i;
two numbers with an asterisk in between. i*j: nlo = i; nhi = j;
- Parameters
file
: name of source file for error messageline
: line number in source file for error messagestr
: string to be processednmin
: smallest possible lower boundnmax
: largest allowed upper boundnlo
: lower boundnhi
: upper bounderror
: pointer to Error class for out-of-bounds messages
-
int
LAMMPS_NS::utils
::
expand_args
(const char *file, int line, int narg, char **arg, int mode, char **&earg, LAMMPS *lmp) Expand list of arguments when containing fix/compute wildcards
This function searches the list of arguments in arg for strings of the kind c_ID[*] or f_ID[*] referring to computes or fixes. Any such strings are replaced by one or more strings with the ‘*’ character replaced by the corresponding possible numbers as determined from the fix or compute instance. Other strings are just copied. If the mode parameter is set to 0, expand global vectors, but not global arrays; if it is set to 1, expand global arrays (by column) but not global vectors.
If any expansion happens, the earg list and all its strings are new allocations and must be freed explicitly by the caller. Otherwise arg and earg will point to the same address and no explicit de-allocation is needed by the caller.
- Return
number of arguments in expanded list
- Parameters
file
: name of source file for error messageline
: line number in source file for error messagenarg
: number of arguments in current listarg
: argument list, possibly containing wildcardsmode
: select between global vectors(=0) and arrays (=1)earg
: new argument list with wildcards expandedlmp
: pointer to top-level LAMMPS class instance
4.8.7. Convenience functions
-
void
LAMMPS_NS::utils
::
logmesg
(LAMMPS *lmp, const std::string &mesg) Send message to screen and logfile, if available
This function simplifies the repetitive task of outputting some message to both the screen and/or the log file. In combination with using fmt::format(), which returns the formatted text in a std::string() instance, this can be used to reduce operations previously requiring several lines of code to a single statement.
- Parameters
lmp
: pointer to LAMMPS class instancemesg
: message to be printed
-
std::string
LAMMPS_NS::utils
::
getsyserror
() return a string representing the current system error status
This is a wrapper around calling strerror(errno).
- Return
error string
-
std::string
LAMMPS_NS::utils
::
check_packages_for_style
(const std::string &style, const std::string &name, LAMMPS *lmp) Report if a requested style is in a package or may have a typo
- Return
string usable for error messages
- Parameters
style
: type of style that is to be checked forname
: name of style that was not foundlmp
: pointer to top-level LAMMPS class instance
-
double
LAMMPS_NS::utils
::
timespec2seconds
(const std::string ×pec) Convert a time string to seconds
The strings “off” and “unlimited” result in -1
- Return
total in seconds
- Parameters
timespec
: a string in the following format: ([[HH:]MM:]SS)
-
int
LAMMPS_NS::utils
::
date2num
(const std::string &date) Convert a LAMMPS version date to a number
This will generate a number YYYYMMDD from a date string (with or without blanks) that is suitable for numerical comparisons, i.e. later dates will generate a larger number.
The day may or may not have a leading zero, the month is identified by the first 3 letters (so there may be more) and the year may be 2 or 4 digits (the missing 2 digits will be assumed as 20. That is 04 corresponds to 2004).
No check is made whether the date is valid.
- Return
date code
- Parameters
date
: string in the format (Day Month Year)
4.8.8. Customized standard functions
-
void
LAMMPS_NS::utils
::
merge_sort
(int *index, int num, void *ptr, int (*comp)(int, int, void*)) Custom merge sort implementation
This function provides a custom upward hybrid merge sort implementation with support to pass an opaque pointer to the comparison function, e.g. for access to class members. This avoids having to use global variables. For improved performance, it uses an in-place insertion sort on initial chunks of up to 64 elements and switches to merge sort from then on.
- Parameters
index
: Array with indices to be sortednum
: Length of the index arrayptr
: Pointer to opaque object passed to comparison functioncomp
: Pointer to comparison function
4.9. Tokenizer classes
The purpose of the tokenizer classes is to simplify the recurring task
of breaking lines of text down into words and/or numbers.
Traditionally, LAMMPS code would be using the strtok()
function from
the C library for that purpose, but that function has two significant
disadvantages: 1) it cannot be used concurrently from different LAMMPS
instances since it stores its status in a global variable and 2) it
modifies the string that it is processing. These classes were
implemented to avoid both of these issues and also to reduce the amount
of code that needs to be written.
The basic procedure is to create an instance of the tokenizer class with the string to be processed as an argument and then do a loop until all available tokens are read. The constructor has a default set of separator characters, but that can be overridden. The default separators are all “whitespace” characters, i.e. the space character, the tabulator character, the carriage return character, the linefeed character, and the form feed character.
#include "tokenizer.h"
#include <cstdlib>
#include <string>
#include <iostream>
using namespace LAMMPS_NS;
int main(int, char **)
{
const char *path = getenv("PATH");
if (path != nullptr) {
Tokenizer p(path,":");
while (p.has_next())
std::cout << "Entry: " << p.next() << "\n";
}
return 0;
}
Most tokenizer operations cannot fail except for
LAMMPS_NS::Tokenizer::next()
(when used without first
checking with LAMMPS_NS::Tokenizer::has_next()
) and
LAMMPS_NS::Tokenizer::skip()
. In case of failure, the class
will throw an exception, so you may need to wrap the code using the
tokenizer into a try
/ catch
block to handle errors. The
LAMMPS_NS::ValueTokenizer
class may also throw an exception
when a (type of) number is requested as next token that is not
compatible with the string representing the next word.
#include "tokenizer.h"
#include <cstdlib>
#include <string>
#include <iostream>
using namespace LAMMPS_NS;
int main(int, char **)
{
const char *text = "1 2 3 4 5 20.0 21 twentytwo 2.3";
double num1(0),num2(0),num3(0),num4(0);
ValueTokenizer t(text);
// read 4 doubles after skipping over 5 numbers
try {
t.skip(5);
num1 = t.next_double();
num2 = t.next_double();
num3 = t.next_double();
num4 = t.next_double();
} catch (TokenizerException &e) {
std::cout << "Reading numbers failed: " << e.what() << "\n";
}
std::cout << "Values: " << num1 << " " << num2 << " " << num3 << " " << num4 << "\n";
return 0;
}
This code example should produce the following output:
Reading numbers failed: Not a valid floating-point number: 'twentytwo'
Values: 20 21 0 0
-
class
LAMMPS_NS
::
Tokenizer
Public Functions
-
Tokenizer
(const std::string &str, const std::string &separators = TOKENIZER_DEFAULT_SEPARATORS) Class for splitting text into words
This tokenizer will break down a string into sub-strings (i.e words) separated by the given separator characters.
- See also
- Parameters
str
: string to be processedseparators
: string with separator characters (default: ” \t\r\n\f”)
-
void
reset
() Re-position the tokenizer state to the first word, i.e. the first non-separator character
-
void
skip
(int n) Skip over a given number of tokens
- Parameters
n
: number of tokens to skip over
-
bool
has_next
() const Indicate whether more tokens are available
- Return
true if there are more tokens, false if not
-
bool
contains
(const std::string &str) const Search the text to be processed for a sub-string.
- Return
true if string was found, false if not
- Parameters
str
: string to be searched for
-
std::string
next
() Retrieve next token.
- Return
string with the next token
-
size_t
count
() Count number of tokens in text.
- Return
number of counted tokens
-
std::vector<std::string>
as_vector
() Retrieve the entire text converted to an STL vector of tokens.
- Return
The STL vector
-
-
class
LAMMPS_NS
::
TokenizerException
: public exception Subclassed by InvalidFloatException, InvalidIntegerException
Public Functions
-
TokenizerException
(const std::string &msg, const std::string &token) Thrown during retrieving or skipping tokens
- Parameters
msg
: String with error messagetoken
: String of the token/word that caused the error
-
const char *
what
() const Retrieve message describing the thrown exception
- Return
string with error message
-
-
class
LAMMPS_NS
::
ValueTokenizer
Public Functions
-
ValueTokenizer
(const std::string &str, const std::string &separators = TOKENIZER_DEFAULT_SEPARATORS) Class for reading text with numbers
- See also
- See
Tokenizer InvalidIntegerException InvalidFloatException
- Parameters
str
: String to be processedseparators
: String with separator characters (default: ” \t\r\n\f”)
-
std::string
next_string
() Retrieve next token
- Return
string with next token
-
tagint
next_tagint
() Retrieve next token and convert to tagint
- Return
value of next token
-
bigint
next_bigint
() Retrieve next token and convert to bigint
- Return
value of next token
-
int
next_int
() Retrieve next token and convert to int
- Return
value of next token
-
double
next_double
() Retrieve next token and convert to double
- Return
value of next token
-
bool
has_next
() const Indicate whether more tokens are available
- Return
true if there are more tokens, false if not
-
bool
contains
(const std::string &value) const Search the text to be processed for a sub-string.
- Return
true if string was found, false if not
- Parameters
value
: string with value to be searched for
-
void
skip
(int ntokens) Skip over a given number of tokens
- Parameters
n
: number of tokens to skip over
-
size_t
count
() Count number of tokens in text.
- Return
number of counted tokens
-
-
class
InvalidIntegerException
: public TokenizerException
-
class
InvalidFloatException
: public TokenizerException
4.10. File reader classes
The purpose of the file reader classes is to simplify the recurring task
of reading and parsing files. They can use the
LAMMPS_NS::ValueTokenizer
class to process the read in
text. The LAMMPS_NS::TextFileReader
is a more general
version while LAMMPS_NS::PotentialFileReader
is specialized
to implement the behavior expected for looking up and reading/parsing
files with potential parameters in LAMMPS. The potential file reader
class requires a LAMMPS instance, requires to be run on MPI rank 0 only,
will use the LAMMPS_NS::utils::get_potential_file_path()
function to look up and open the file, and will call the
LAMMPS_NS::Error
class in case of failures to read or to
convert numbers, so that LAMMPS will be aborted.
PotentialFileReader reader(lmp, file, "coul/streitz");
char * line;
while((line = reader.next_line(NPARAMS_PER_LINE))) {
try {
ValueTokenizer values(line);
std::string iname = values.next_string();
int ielement;
for (ielement = 0; ielement < nelements; ielement++)
if (iname == elements[ielement]) break;
if (nparams == maxparam) {
maxparam += DELTA;
params = (Param *) memory->srealloc(params,maxparam*sizeof(Param),
"pair:params");
}
params[nparams].ielement = ielement;
params[nparams].chi = values.next_double();
params[nparams].eta = values.next_double();
params[nparams].gamma = values.next_double();
params[nparams].zeta = values.next_double();
params[nparams].zcore = values.next_double();
} catch (TokenizerException & e) {
error->one(FLERR, e.what());
}
nparams++;
}
A file that would be parsed by the reader code fragment looks like this:
# DATE: 2015-02-19 UNITS: metal CONTRIBUTOR: Ray Shan CITATION: Streitz and Mintmire, Phys Rev B, 50, 11996-12003 (1994) # # X (eV) J (eV) gamma (1/AA) zeta (1/AA) Z (e) Al 0.000000 10.328655 0.000000 0.968438 0.763905 O 5.484763 14.035715 0.000000 2.143957 0.000000
-
class
LAMMPS_NS
::
TextFileReader
Public Functions
-
TextFileReader
(const std::string &filename, const std::string &filetype) Class for reading and parsing text files
The value of the class member variable ignore_comments controls whether any text following the pound sign (#) should be ignored (true) or not (false). Default: true, i.e. ignore.
- See also
- Parameters
filename
: Name of file to be readfiletype
: Description of file type for error messages
-
~TextFileReader
() Closes the file
-
void
skip_line
() Read the next line and ignore it
-
char *
next_line
(int nparams = 0) Read the next line(s) until nparams words have been read.
This reads a line and counts the words in it, if the number is less than the requested number, it will read the next line, as well. Output will be a string with all read lines combined. The purpose is to somewhat replicate the reading behavior of formatted files in Fortran.
If the ignore_comments class member has the value true, then any text read in is truncated at the first ‘#’ character.
- Return
String with the concatenated text
- Parameters
nparams
: Number of words that must be read. Default: 0
-
void
next_dvector
(double *list, int n) Read lines until n doubles have been read and stored in array list
This reads lines from the file using the next_line() function, and splits them into floating-point numbers using the ValueTokenizer class and stores the number is the provided list.
- Parameters
list
: Pointer to array with suitable storage for n doublesn
: Number of doubles to be read
-
ValueTokenizer
next_values
(int nparams, const std::string &separators = TOKENIZER_DEFAULT_SEPARATORS) Read text until nparams words are read and passed to a tokenizer object for custom parsing.
This reads lines from the file using the next_line() function, and splits them into floating-point numbers using the ValueTokenizer class and stores the number is the provided list.
- Return
ValueTokenizer object for read in text
- Parameters
nparams
: Number of words to be readseparators
: String with list of separators.
Public Members
-
bool
ignore_comments
Controls whether comments are ignored.
-
-
class
LAMMPS_NS
::
PotentialFileReader
: protected Pointers Public Functions
-
PotentialFileReader
(class LAMMPS *lmp, const std::string &filename, const std::string &potential_name, const int auto_convert = 0) Class for reading and parsing LAMMPS potential files
The value of the class member variable ignore_comments controls whether any text following the pound sign (#) should be ignored (true) or not (false). Default: true, i.e. ignore.
- See also
- Parameters
lmp
: Pointer to LAMMPS instancefilename
: Name of file to be readpotential_name
: Name of potential style for error messagesauto_convert
: Bitmask of supported unit conversions
-
~PotentialFileReader
() Closes the file
-
void
ignore_comments
(bool value) Set comment (= text after ‘#’) handling preference for the file to be read
- Parameters
value
: Comment text is ignored if true, or not if false
-
void
skip_line
() Read a line but ignore its content
-
char *
next_line
(int nparams = 0) Read the next line(s) until nparams words have been read.
This reads a line and counts the words in it, if the number is less than the requested number, it will read the next line, as well. Output will be a string with all read lines combined. The purpose is to somewhat replicate the reading behavior of formatted files in Fortran.
- Return
String with the concatenated text
- Parameters
nparams
: Number of words that must be read. Default: 0
-
void
next_dvector
(double *list, int n) Read lines until n doubles have been read and stored in array list
This reads lines from the file using the next_line() function, and splits them into floating-point numbers using the ValueTokenizer class and stores the number is the provided list.
- Parameters
list
: Pointer to array with suitable storage for n doublesn
: Number of doubles to be read
-
ValueTokenizer
next_values
(int nparams, const std::string &separators = TOKENIZER_DEFAULT_SEPARATORS) Read text until nparams words are read and passed to a tokenizer object for custom parsing.
This reads lines from the file using the next_line() function, and splits them into floating-point numbers using the ValueTokenizer class and stores the number is the provided list.
- Return
ValueTokenizer object for read in text
- Parameters
nparams
: Number of words to be readseparators
: String with list of separators.
-
double
next_double
() Read next line and convert first word to a double
- Return
Value of first word in line as double
-
int
next_int
() Read next line and convert first word to an int
- Return
Value of first word in line as int
-
tagint
next_tagint
() Read next line and convert first word to a tagint
- Return
Value of first word in line as tagint
-
bigint
next_bigint
() Read next line and convert first word to a bigint
- Return
Value of first word in line as bigint
-
std::string
next_string
() Read next line and return first word
- Return
First word of read in line
-
4.11. Memory pool classes
The memory pool classes are used for cases where otherwise many small memory allocations would be needed and where the data would be either all used or all freed. One example for that is the storage of neighbor lists. The memory management strategy is based on the assumption that allocations will be in chunks of similar sizes. The allocation is then not done per individual call for a reserved chunk of memory, but for a “page” that can hold multiple chunks of data. A parameter for the maximum chunk size must be provided, as that is used to determine whether a new page of memory must be used.
The MyPage
class offers two ways to
reserve a chunk: 1) with get()
the
chunk size needs to be known in advance, 2) with vget()
a pointer to the next chunk is returned, but
its size is registered later with vgot()
.
MyPage
#include "my_page.h"
using namespace LAMMPS_NS;
MyPage<double> *dpage = new MyPage<double>;
// max size of chunk: 256, size of page: 10240 doubles (=81920 bytes)
dpage->init(256,10240);
double **build_some_lists(int num)
{
dpage->reset();
double **dlist = new double*[num];
for (int i=0; i < num; ++i) {
double *dptr = dpage.vget();
int jnum = 0;
for (int j=0; j < jmax; ++j) {
// compute some dvalue for eligible loop index j
dptr[j] = dvalue;
++jnum;
}
if (dpage.status() != 0) {
// handle out of memory or jnum too large errors
}
dpage.vgot(jnum);
dlist[i] = dptr;
}
return dlist;
}
-
template<class
T
>
classLAMMPS_NS
::
MyPage
Templated class for storing chunks of datums in pages.
The size of the chunk may vary from call to call, but must be less or equal than the maxchunk setting. The chunks are not returnable like with malloc() (i.e. you cannot call free() on them individually). One can only reset and start over. The purpose of this class is to replace many small memory allocations via malloc() with a few large ones. Since the pages are never freed until the class is re-initialized, they can be re-used without having to re-allocate them by calling the reset() method.
The settings maxchunk, pagesize, and pagedelta control the memory allocation strategy. The maxchunk value represents the expected largest number of items per chunk. If there is less space left on the current page, a new page is allocated for the next chunk. The pagesize value represents how many items can fit on a single page. It should have space for multiple chunks of size maxchunk. The combination of these two parameters determines how much memory is wasted by either switching to the next page too soon or allocating too large pages that never get properly used. It is an error, if a requested chunk is larger than maxchunk. The pagedelta parameter determines how many pages are allocated in one go. In combination with the pagesize setting, this determines how often blocks of memory get allocated (fewer allocations will result in faster execution).
- Note
This is a template class with explicit instantiation. If the class is used with a new data type a new explicit instantiation may need to be added at the end of the file
src/my_page.cpp
to avoid symbol lookup errors.
Public Functions
-
MyPage
() Create a class instance
Need to call init() before use to define allocation settings
-
int
init
(int user_maxchunk = 1, int user_pagesize = 1024, int user_pagedelta = 1) (Re-)initialize the set of pages and allocation parameters.
This also frees all previously allocated storage and allocates the first page(s).
- Return
1 if there were invalid parameters, 2 if there was an allocation error or 0 if successful
- Parameters
user_maxchunk
: Expected maximum number of items for one chunkuser_pagesize
: Number of items on a single memory pageuser_pagedelta
: Number of pages to allocate with one malloc
-
T *
get
(int n = 1) Pointer to location that can store N items.
This will allocate more pages as needed. If the parameter N is larger than the maxchunk setting an error is flagged.
- Return
memory location or null pointer, if error or allocation failed
- Parameters
n
: number of items for which storage is requested
-
T *
vget
() Get pointer to location that can store maxchunk items.
This will return the same pointer as the previous call to this function unless vgot() is called afterwards to record how many items of the chunk were actually used.
- Return
pointer to chunk of memory or null pointer if run out of memory
-
void
vgot
(int n) Mark N items as used of the chunk reserved with a preceding call to vget().
This will advance the internal pointer inside the current memory page. It is not necessary to call this function for N = 0, that is the reserved storage was not used. A following call to vget() will then reserve the same location again. It is an error if N > maxchunk.
- Parameters
n
: Number of items used in previously reserved chunk
-
void
reset
() Reset state of memory pool without freeing any memory
-
double
size
() const Return total size of allocated pages
- Return
total storage used in bytes
-
int
status
() const Return error status
- Return
0 if no error, 1 requested chunk size > maxchunk, 2 if malloc failed
-
template<class
T
>
classLAMMPS_NS
::
MyPoolChunk
Templated class for storing chunks of datums in pages.
The size of the chunk may vary from call to call between the minchunk and maxchunk setting. Chunks may be returned to the pool for re-use. Chunks can be reserved in nbin different sizes between minchunk and maxchunk. The chunksperpage setting specifies how many chunks are stored on any page and the pagedelta setting determines how many pages are allocated in one go. Pages are never freed, so they can be re-used without re-allocation.
- Note
This is a template class with explicit instantiation. If the class is used with a new data type a new explicit instantiation may need to be added at the end of the file
src/my_pool_chunk.cpp
to avoid symbol lookup errors.
Public Functions
-
MyPoolChunk
(int user_minchunk = 1, int user_maxchunk = 1, int user_nbin = 1, int user_chunkperpage = 1024, int user_pagedelta = 1) Create a class instance and set memory pool parameters
- Parameters
user_minchunk
: Minimal chunk sizeuser_maxchunk
: Maximal chunk sizeuser_nbin
: Number of bins of different chunk sizesuser_chunkperpage
: Number of chunks per pageuser_pagedelta
: Number of pages to allocate in one go
-
~MyPoolChunk
() Destroy class instance and free all allocated memory
-
T *
get
(int &index) Return pointer/index of unused chunk of size maxchunk
- Return
Pointer to requested chunk of storage
- Parameters
index
: Index of chunk in memory pool
-
T *
get
(int n, int &index) Return pointer/index of unused chunk of size N
- Return
Pointer to requested chunk of storage
- Parameters
n
: Size of chunkindex
: Index of chunk in memory pool
-
void
put
(int index) Put indexed chunk back into memory pool via free list
- Parameters
index
: Memory chunk index returned by call to get()
-
double
size
() const Return total size of allocated pages
- Return
total storage used in bytes
-
int
status
() const Return error status
- Return
0 if no error, 1 if invalid input, 2 if malloc() failed, 3 if chunk > maxchunk
4.12. Eigensolver functions
The MathEigen
sub-namespace of the LAMMPS_NS
namespace contains
functions and classes for eigensolvers. Currently only the
jacobi3 function
is used in various
places in LAMMPS. That function is built on top of a group of more
generic eigensolvers that are maintained in the math_eigen_impl.h
header file. This header contains the implementation of three template
classes:
“Jacobi” calculates all of the eigenvalues and eigenvectors of a dense, symmetric, real matrix.
The “PEigenDense” class only calculates the principal eigenvalue (ie. the largest or smallest eigenvalue), and its corresponding eigenvector. However it is much more efficient than “Jacobi” when applied to large matrices (larger than 13x13). PEigenDense also can understand complex-valued Hermitian matrices.
The “LambdaLanczos” class is a generalization of “PEigenDense” which can be applied to arbitrary sparse matrices.
The “math_eigen_impl.h” code is an amalgamation of jacobi_pd by Andrew Jewett at Scripps Research (under CC0-1.0 license) and Lambda Lanczos by Yuya Kurebayashi at Tohoku University (under MIT license)
-
int
MathEigen
::
jacobi3
(double const *const *mat, double *eval, double **evec) A specialized function which finds the eigenvalues and eigenvectors of a 3x3 matrix (in double ** format).
- Return
0 if eigenvalue calculation converged, 1 if it failed
- Parameters
mat
: the 3x3 matrix you wish to diagonalizeeval
: store the eigenvalues hereevec
: store the eigenvectors here…
-
int
MathEigen
::
jacobi3
(double const mat[3][3], double *eval, double evec[3][3]) This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
4.13. Communication buffer coding with ubuf
LAMMPS uses communication buffers where it collects data from various
class instances and then exchanges the data with neighboring sub-domains.
For simplicity those buffers are defined as double
buffers and
used for doubles and integer numbers. This presents a unique problem
when 64-bit integers are used. While the storage needed for a double
is also 64-bit, it cannot be used by a simple assignment. To get around
that limitation, LAMMPS uses the ubuf
union. It is used in the various “pack” and “unpack” functions in the
LAMMPS classes to store and retrieve integers that may be 64-bit from
the communication buffers.
-
union
LAMMPS_NS
::
ubuf
- #include <lmptype.h>
Data structure for packing 32-bit and 64-bit integers into double (communication) buffers
Using this union avoids aliasing issues by having member types (double, int) referencing the same buffer memory location.
The explicit constructor for 32-bit integers prevents compilers from (incorrectly) calling the double constructor when storing an int into a double buffer.
Usage:
To copy an integer into a double buffer:double buf[2]; int foo = 1; tagint bar = 2<<40; buf[1] = ubuf(foo).d; buf[2] = ubuf(bar).d;
To copy from a double buffer back to an int:foo = (int) ubuf(buf[1]).i; bar = (tagint) ubuf(buf[2]).i;
The typecasts prevent compiler warnings about possible truncation issues.
Public Functions
-
ubuf
(const double &arg)
-
ubuf
(const int64_t &arg)
-
ubuf
(const int &arg)
Public Members
-
double
d
-
int64_t
i
-