pylammps: make use of lammps_last_thermo

this now avoids parsing LAMMPS output to extract thermo data, but instead uses
the new lammps_last_thermo library function
This commit is contained in:
Richard Berger
2023-06-09 02:29:30 -06:00
parent ecf7c24e87
commit fe45b766c3
2 changed files with 31 additions and 53 deletions

View File

@ -746,6 +746,11 @@ class lammps(object):
return self.lib.lammps_get_thermo(self.lmp,name) return self.lib.lammps_get_thermo(self.lmp,name)
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
@property
def last_thermo_step(self):
with ExceptionCheck(self):
ptr = self.lib.lammps_last_thermo(self.lmp, c_char_p("step".encode()), 0)
return cast(ptr, POINTER(self.c_bigint)).contents.value
def last_thermo(self): def last_thermo(self):
"""Get a dictionary of the last thermodynamic output """Get a dictionary of the last thermodynamic output
@ -760,9 +765,7 @@ class lammps(object):
""" """
rv = dict() rv = dict()
with ExceptionCheck(self): mystep = self.last_thermo_step
ptr = self.lib.lammps_last_thermo(self.lmp, c_char_p("step".encode()), 0)
mystep = cast(ptr, POINTER(self.c_bigint)).contents.value
if mystep < 0: if mystep < 0:
return None return None

View File

@ -377,55 +377,6 @@ class variable_set:
def __repr__(self): def __repr__(self):
return self.__str__() return self.__str__()
# -------------------------------------------------------------------------
def get_thermo_data(output):
""" traverse output of runs and extract thermo data columns """
if isinstance(output, str):
lines = output.splitlines()
else:
lines = output
runs = []
columns = []
in_run = False
current_run = {}
for line in lines:
if line.startswith("Per MPI rank memory allocation"):
in_run = True
elif in_run and len(columns) == 0:
# first line after memory usage are column names
columns = line.split()
current_run = {}
for col in columns:
current_run[col] = []
elif line.startswith("Loop time of "):
in_run = False
columns = []
thermo_data = variable_set('ThermoData', current_run)
r = {'thermo' : thermo_data }
runs.append(namedtuple('Run', list(r.keys()))(*list(r.values())))
elif in_run and len(columns) > 0:
items = line.split()
# Convert thermo output and store it.
# It must have the same number of columns and
# all of them must be convertible to floats.
# Otherwise we ignore the line
if len(items) == len(columns):
try:
values = [float(x) for x in items]
for i, col in enumerate(columns):
current_run[col].append(values[i])
except ValueError:
# cannot convert. must be a non-thermo output. ignore.
pass
return runs
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
@ -573,6 +524,13 @@ class PyLammps(object):
if self.enable_cmd_history: if self.enable_cmd_history:
self._cmd_history.append(cmd) self._cmd_history.append(cmd)
def _append_run_thermo(self, thermo):
for k, v in thermo.items():
if k in self._current_run:
self._current_run[k].append(v)
else:
self._current_run[k] = [v]
def run(self, *args, **kwargs): def run(self, *args, **kwargs):
""" """
Execute LAMMPS run command with given arguments Execute LAMMPS run command with given arguments
@ -581,8 +539,25 @@ class PyLammps(object):
:py:attr:`PyLammps.runs`. The latest run can be retrieved by :py:attr:`PyLammps.runs`. The latest run can be retrieved by
:py:attr:`PyLammps.last_run`. :py:attr:`PyLammps.last_run`.
""" """
self._current_run = {}
self._last_thermo_step = -1
def end_of_step_callback(lmp):
if self.lmp.last_thermo_step == self._last_thermo_step: return
thermo = self.lmp.last_thermo()
self._append_run_thermo(thermo)
self._last_thermo_step = thermo['Step']
import __main__
__main__._PyLammps_end_of_step_callback = end_of_step_callback
self.fix("__pylammps_internal_run_callback", "all", "python/invoke", "1", "end_of_step", "_PyLammps_end_of_step_callback")
output = self.__getattr__('run')(*args, **kwargs) output = self.__getattr__('run')(*args, **kwargs)
self.runs += get_thermo_data(output) self.unfix("__pylammps_internal_run_callback")
self._append_run_thermo(self.lmp.last_thermo())
thermo_data = variable_set('ThermoData', self._current_run)
r = {'thermo' : thermo_data }
self.runs.append(namedtuple('Run', list(r.keys()))(*list(r.values())))
return output return output
@property @property