@ -6,7 +6,7 @@
|
||||
"configurationType": "Debug",
|
||||
"buildRoot": "${workspaceRoot}\\build\\${name}",
|
||||
"installRoot": "${workspaceRoot}\\install\\${name}",
|
||||
"cmakeCommandArgs": "-S ${workspaceRoot}\\cmake -C ${workspaceRoot}\\cmake\\presets\\windows.cmake -DENABLE_TESTING=on",
|
||||
"cmakeCommandArgs": "-C ${workspaceRoot}\\cmake\\presets\\windows.cmake",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
@ -25,6 +25,54 @@
|
||||
"name": "LAMMPS_EXCEPTIONS",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "PKG_PYTHON",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "ENABLE_TESTING",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "x64-Release-MSVC",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Release",
|
||||
"buildRoot": "${workspaceRoot}\\build\\${name}",
|
||||
"installRoot": "${workspaceRoot}\\install\\${name}",
|
||||
"cmakeCommandArgs": "-C ${workspaceRoot}\\cmake\\presets\\windows.cmake",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"variables": [
|
||||
{
|
||||
"name": "BUILD_SHARED_LIBS",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "BUILD_TOOLS",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "LAMMPS_EXCEPTIONS",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "PKG_PYTHON",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "ENABLE_TESTING",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -34,11 +82,16 @@
|
||||
"configurationType": "Debug",
|
||||
"buildRoot": "${workspaceRoot}\\build\\${name}",
|
||||
"installRoot": "${workspaceRoot}\\install\\${name}",
|
||||
"cmakeCommandArgs": "-S ${workspaceRoot}\\cmake -C ${workspaceRoot}\\cmake\\presets\\windows.cmake -DENABLE_TESTING=on",
|
||||
"cmakeCommandArgs": "-C ${workspaceRoot}\\cmake\\presets\\windows.cmake",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "clang_cl_x64" ],
|
||||
"variables": [
|
||||
{
|
||||
"name": "BUILD_SHARED_LIBS",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "BUILD_TOOLS",
|
||||
"value": "True",
|
||||
@ -48,6 +101,16 @@
|
||||
"name": "LAMMPS_EXCEPTIONS",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "PKG_PYTHON",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "ENABLE_TESTING",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -57,7 +120,7 @@
|
||||
"configurationType": "Debug",
|
||||
"buildRoot": "${workspaceRoot}\\build\\${name}",
|
||||
"installRoot": "${workspaceRoot}\\install\\${name}",
|
||||
"cmakeCommandArgs": "-S ${workspaceRoot}\\cmake -C ${workspaceRoot}\\cmake\\presets\\windows.cmake -DENABLE_TESTING=on -DCMAKE_CXX_COMPILER=icx -DCMAKE_C_COMPILER=icx -DBUILD_MPI=off",
|
||||
"cmakeCommandArgs": "-C ${workspaceRoot}\\cmake\\presets\\windows.cmake -DCMAKE_CXX_COMPILER=icx -DCMAKE_C_COMPILER=icx",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
@ -76,6 +139,21 @@
|
||||
"name": "LAMMPS_EXCEPTIONS",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "PKG_PYTHON",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "ENABLE_TESTING",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "BUILD_MPI",
|
||||
"value": "False",
|
||||
"type": "BOOL"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -85,7 +163,7 @@
|
||||
"configurationType": "Debug",
|
||||
"buildRoot": "${workspaceRoot}\\build\\${name}",
|
||||
"installRoot": "${workspaceRoot}\\install\\${name}",
|
||||
"cmakeCommandArgs": "-S ${workspaceRoot}\\cmake -C ${workspaceRoot}\\cmake\\presets\\windows.cmake -DENABLE_TESTING=off -DCMAKE_CXX_COMPILER=icl -DCMAKE_C_COMPILER=icl -DCMAKE_Fortran_COMPILER=ifort -DBUILD_MPI=off",
|
||||
"cmakeCommandArgs": "-C ${workspaceRoot}\\cmake\\presets\\windows.cmake -DCMAKE_CXX_COMPILER=icl -DCMAKE_C_COMPILER=icl -DCMAKE_Fortran_COMPILER=ifort",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
@ -104,8 +182,23 @@
|
||||
"name": "LAMMPS_EXCEPTIONS",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "PKG_PYTHON",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "ENABLE_TESTING",
|
||||
"value": "False",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "BUILD_MPI",
|
||||
"value": "False",
|
||||
"type": "BOOL"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,6 +205,9 @@ Convenience functions
|
||||
.. doxygenfunction:: logmesg(LAMMPS *lmp, const std::string &mesg)
|
||||
:project: progguide
|
||||
|
||||
.. doxygenfunction:: flush_buffers(LAMMPS *lmp)
|
||||
:project: progguide
|
||||
|
||||
.. doxygenfunction:: getsyserror
|
||||
:project: progguide
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ functions. They do not directly call the LAMMPS library.
|
||||
- :cpp:func:`lammps_fix_external_set_virial_peratom`
|
||||
- :cpp:func:`lammps_fix_external_set_vector_length`
|
||||
- :cpp:func:`lammps_fix_external_set_vector`
|
||||
- :cpp:func:`lammps_flush_buffers`
|
||||
- :cpp:func:`lammps_free`
|
||||
- :cpp:func:`lammps_is_running`
|
||||
- :cpp:func:`lammps_force_timeout`
|
||||
@ -72,6 +73,11 @@ where such memory buffers were allocated that require the use of
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_flush_buffers
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_free
|
||||
:project: progguide
|
||||
|
||||
|
||||
@ -164,6 +164,7 @@ class lammps(object):
|
||||
self.lib.lammps_open.restype = c_void_p
|
||||
self.lib.lammps_open_no_mpi.restype = c_void_p
|
||||
self.lib.lammps_close.argtypes = [c_void_p]
|
||||
self.lib.lammps_flush_buffers.argtypes = [c_void_p]
|
||||
self.lib.lammps_free.argtypes = [c_void_p]
|
||||
|
||||
self.lib.lammps_file.argtypes = [c_void_p, c_char_p]
|
||||
@ -1118,6 +1119,16 @@ class lammps(object):
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def flush_buffers(self):
|
||||
"""Flush output buffers
|
||||
|
||||
This is a wrapper around the :cpp:func:`lammps_flush_buffers`
|
||||
function of the C-library interface.
|
||||
"""
|
||||
self.lib.lammps_flush_buffers(self.lmp)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def set_variable(self,name,value):
|
||||
"""Set a new value for a LAMMPS string style variable
|
||||
|
||||
|
||||
@ -92,7 +92,7 @@ class numpy_wrapper:
|
||||
if dim == LAMMPS_AUTODETECT:
|
||||
if dtype in (LAMMPS_INT_2D, LAMMPS_DOUBLE_2D, LAMMPS_INT64_2D):
|
||||
# TODO add other fields
|
||||
if name in ("x", "v", "f", "x0", "omega", "angmom", "torque", "vforce", "vest"):
|
||||
if name in ("x", "v", "f", "x0","omega", "angmom", "torque", "csforce", "vforce", "vest"):
|
||||
dim = 3
|
||||
elif name == "smd_data_9":
|
||||
dim = 9
|
||||
|
||||
@ -20,47 +20,47 @@
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
import select
|
||||
import sys
|
||||
import tempfile
|
||||
from collections import namedtuple
|
||||
|
||||
from .core import lammps
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
class OutputCapture(object):
|
||||
""" Utility class to capture LAMMPS library output """
|
||||
|
||||
def __init__(self):
|
||||
self.stdout_pipe_read, self.stdout_pipe_write = os.pipe()
|
||||
self.stdout_fd = 1
|
||||
self.captured_output = ""
|
||||
|
||||
def __enter__(self):
|
||||
self.stdout = os.dup(self.stdout_fd)
|
||||
os.dup2(self.stdout_pipe_write, self.stdout_fd)
|
||||
self.tmpfile = tempfile.TemporaryFile(mode='w+b')
|
||||
|
||||
sys.stdout.flush()
|
||||
|
||||
# make copy of original stdout
|
||||
self.stdout_orig = os.dup(self.stdout_fd)
|
||||
|
||||
# replace stdout and redirect to temp file
|
||||
os.dup2(self.tmpfile.fileno(), self.stdout_fd)
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
os.dup2(self.stdout, self.stdout_fd)
|
||||
os.close(self.stdout)
|
||||
os.close(self.stdout_pipe_read)
|
||||
os.close(self.stdout_pipe_write)
|
||||
|
||||
# check if we have more to read from the pipe
|
||||
def more_data(self, pipe):
|
||||
r, _, _ = select.select([pipe], [], [], 0)
|
||||
return bool(r)
|
||||
|
||||
# read the whole pipe
|
||||
def read_pipe(self, pipe):
|
||||
out = ""
|
||||
while self.more_data(pipe):
|
||||
out += os.read(pipe, 1024).decode()
|
||||
return out
|
||||
os.dup2(self.stdout_orig, self.stdout_fd)
|
||||
os.close(self.stdout_orig)
|
||||
self.tmpfile.close()
|
||||
|
||||
@property
|
||||
def output(self):
|
||||
return self.read_pipe(self.stdout_pipe_read)
|
||||
sys.stdout.flush()
|
||||
self.tmpfile.flush()
|
||||
self.tmpfile.seek(0, io.SEEK_SET)
|
||||
self.captured_output = self.tmpfile.read().decode('utf-8')
|
||||
return self.captured_output
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@ -109,9 +109,9 @@ class AtomList(object):
|
||||
"""
|
||||
if index not in self._loaded:
|
||||
if self.dimensions == 2:
|
||||
atom = Atom2D(self._pylmp, index + 1)
|
||||
atom = Atom2D(self._pylmp, index)
|
||||
else:
|
||||
atom = Atom(self._pylmp, index + 1)
|
||||
atom = Atom(self._pylmp, index)
|
||||
self._loaded[index] = atom
|
||||
return self._loaded[index]
|
||||
|
||||
@ -134,6 +134,12 @@ class Atom(object):
|
||||
def __dir__(self):
|
||||
return [k for k in super().__dir__() if not k.startswith('_')]
|
||||
|
||||
def get(self, name, index):
|
||||
prop = self._pylmp.lmp.numpy.extract_atom(name)
|
||||
if prop is not None:
|
||||
return prop[index]
|
||||
return None
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
"""
|
||||
@ -141,7 +147,7 @@ class Atom(object):
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return int(self._pylmp.eval("id[%d]" % self.index))
|
||||
return self.get("id", self.index)
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
@ -150,7 +156,7 @@ class Atom(object):
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return int(self._pylmp.eval("type[%d]" % self.index))
|
||||
return self.get("type", self.index)
|
||||
|
||||
@property
|
||||
def mol(self):
|
||||
@ -159,7 +165,7 @@ class Atom(object):
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return self._pylmp.eval("mol[%d]" % self.index)
|
||||
return self.get("mol", self.index)
|
||||
|
||||
@property
|
||||
def mass(self):
|
||||
@ -168,52 +174,114 @@ class Atom(object):
|
||||
|
||||
:type: float
|
||||
"""
|
||||
return self._pylmp.eval("mass[%d]" % self.index)
|
||||
return self.get("mass", self.index)
|
||||
|
||||
@property
|
||||
def radius(self):
|
||||
"""
|
||||
Return the particle radius
|
||||
|
||||
:type: float
|
||||
"""
|
||||
return self.get("radius", self.index)
|
||||
|
||||
@property
|
||||
def position(self):
|
||||
"""
|
||||
:getter: Return position of atom
|
||||
:setter: Set position of atom
|
||||
:type: tuple (float, float, float)
|
||||
:type: numpy.array (float, float, float)
|
||||
"""
|
||||
return (self._pylmp.eval("x[%d]" % self.index),
|
||||
self._pylmp.eval("y[%d]" % self.index),
|
||||
self._pylmp.eval("z[%d]" % self.index))
|
||||
return self.get("x", self.index)
|
||||
|
||||
@position.setter
|
||||
def position(self, value):
|
||||
"""
|
||||
:getter: Return velocity of atom
|
||||
:setter: Set velocity of atom
|
||||
:type: tuple (float, float, float)
|
||||
"""
|
||||
self._pylmp.set("atom", self.index, "x", value[0])
|
||||
self._pylmp.set("atom", self.index, "y", value[1])
|
||||
self._pylmp.set("atom", self.index, "z", value[2])
|
||||
current = self.position
|
||||
current[:] = value
|
||||
|
||||
@property
|
||||
def velocity(self):
|
||||
return (self._pylmp.eval("vx[%d]" % self.index),
|
||||
self._pylmp.eval("vy[%d]" % self.index),
|
||||
self._pylmp.eval("vz[%d]" % self.index))
|
||||
"""
|
||||
:getter: Return velocity of atom
|
||||
:setter: Set velocity of atom
|
||||
:type: numpy.array (float, float, float)
|
||||
"""
|
||||
return self.get("v", self.index)
|
||||
|
||||
@velocity.setter
|
||||
def velocity(self, value):
|
||||
self._pylmp.set("atom", self.index, "vx", value[0])
|
||||
self._pylmp.set("atom", self.index, "vy", value[1])
|
||||
self._pylmp.set("atom", self.index, "vz", value[2])
|
||||
current = self.velocity
|
||||
current[:] = value
|
||||
|
||||
@property
|
||||
def force(self):
|
||||
"""
|
||||
Return the total force acting on the atom
|
||||
|
||||
:type: tuple (float, float, float)
|
||||
:type: numpy.array (float, float, float)
|
||||
"""
|
||||
return (self._pylmp.eval("fx[%d]" % self.index),
|
||||
self._pylmp.eval("fy[%d]" % self.index),
|
||||
self._pylmp.eval("fz[%d]" % self.index))
|
||||
return self.get("f", self.index)
|
||||
|
||||
@force.setter
|
||||
def force(self, value):
|
||||
current = self.force
|
||||
current[:] = value
|
||||
|
||||
@property
|
||||
def torque(self):
|
||||
"""
|
||||
Return the total torque acting on the atom
|
||||
|
||||
:type: numpy.array (float, float, float)
|
||||
"""
|
||||
return self.get("torque", self.index)
|
||||
|
||||
@force.setter
|
||||
def torque(self, value):
|
||||
current = self.torque
|
||||
current[:] = value
|
||||
|
||||
@property
|
||||
def omega(self):
|
||||
"""
|
||||
Return the rotational velocity of the particle
|
||||
|
||||
:type: numpy.array (float, float, float)
|
||||
"""
|
||||
return self.get("torque", self.index)
|
||||
|
||||
@omega.setter
|
||||
def omega(self, value):
|
||||
current = self.torque
|
||||
current[:] = value
|
||||
|
||||
@property
|
||||
def torque(self):
|
||||
"""
|
||||
Return the total torque acting on the particle
|
||||
|
||||
:type: numpy.array (float, float, float)
|
||||
"""
|
||||
return self.get("torque", self.index)
|
||||
|
||||
@torque.setter
|
||||
def torque(self, value):
|
||||
current = self.torque
|
||||
current[:] = value
|
||||
|
||||
@property
|
||||
def angular_momentum(self):
|
||||
"""
|
||||
Return the angular momentum of the particle
|
||||
|
||||
:type: numpy.array (float, float, float)
|
||||
"""
|
||||
return self.get("angmom", self.index)
|
||||
|
||||
@angular_momentum.setter
|
||||
def angular_momentum(self, value):
|
||||
current = self.angular_momentum
|
||||
current[:] = value
|
||||
|
||||
@property
|
||||
def charge(self):
|
||||
@ -222,7 +290,7 @@ class Atom(object):
|
||||
|
||||
:type: float
|
||||
"""
|
||||
return self._pylmp.eval("q[%d]" % self.index)
|
||||
return self.get("q", self.index)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@ -244,39 +312,42 @@ class Atom2D(Atom):
|
||||
|
||||
:getter: Return position of atom
|
||||
:setter: Set position of atom
|
||||
:type: tuple (float, float)
|
||||
:type: numpy.array (float, float)
|
||||
"""
|
||||
return (self._pylmp.eval("x[%d]" % self.index),
|
||||
self._pylmp.eval("y[%d]" % self.index))
|
||||
return super(Atom2D, self).position[0:2]
|
||||
|
||||
@position.setter
|
||||
def position(self, value):
|
||||
self._pylmp.set("atom", self.index, "x", value[0])
|
||||
self._pylmp.set("atom", self.index, "y", value[1])
|
||||
current = self.position
|
||||
current[:] = value
|
||||
|
||||
@property
|
||||
def velocity(self):
|
||||
"""Access to velocity of an atom
|
||||
:getter: Return velocity of atom
|
||||
:setter: Set velocity of atom
|
||||
:type: tuple (float, float)
|
||||
:type: numpy.array (float, float)
|
||||
"""
|
||||
return (self._pylmp.eval("vx[%d]" % self.index),
|
||||
self._pylmp.eval("vy[%d]" % self.index))
|
||||
return super(Atom2D, self).velocity[0:2]
|
||||
|
||||
@velocity.setter
|
||||
def velocity(self, value):
|
||||
self._pylmp.set("atom", self.index, "vx", value[0])
|
||||
self._pylmp.set("atom", self.index, "vy", value[1])
|
||||
current = self.velocity
|
||||
current[:] = value
|
||||
|
||||
@property
|
||||
def force(self):
|
||||
"""Access to force of an atom
|
||||
|
||||
:type: tuple (float, float)
|
||||
:getter: Return force of atom
|
||||
:setter: Set force of atom
|
||||
:type: numpy.array (float, float)
|
||||
"""
|
||||
return (self._pylmp.eval("fx[%d]" % self.index),
|
||||
self._pylmp.eval("fy[%d]" % self.index))
|
||||
return super(Atom2D, self).force[0:2]
|
||||
|
||||
@force.setter
|
||||
def force(self, value):
|
||||
current = self.force
|
||||
current[:] = value
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@ -541,7 +612,8 @@ class PyLammps(object):
|
||||
:getter: Returns an object with properties storing the current system state
|
||||
:type: namedtuple
|
||||
"""
|
||||
output = self.info("system")
|
||||
output = self.lmp_info("system")
|
||||
output = output[output.index("System information:")+1:]
|
||||
d = self._parse_info_system(output)
|
||||
return namedtuple('System', d.keys())(*d.values())
|
||||
|
||||
@ -553,7 +625,8 @@ class PyLammps(object):
|
||||
:getter: Returns an object with properties storing the current communication state
|
||||
:type: namedtuple
|
||||
"""
|
||||
output = self.info("communication")
|
||||
output = self.lmp_info("communication")
|
||||
output = output[output.index("Communication information:")+1:]
|
||||
d = self._parse_info_communication(output)
|
||||
return namedtuple('Communication', d.keys())(*d.values())
|
||||
|
||||
@ -565,7 +638,8 @@ class PyLammps(object):
|
||||
:getter: Returns a list of computes that are currently active in this LAMMPS instance
|
||||
:type: list
|
||||
"""
|
||||
output = self.info("computes")
|
||||
output = self.lmp_info("computes")
|
||||
output = output[output.index("Compute information:")+1:]
|
||||
return self._parse_element_list(output)
|
||||
|
||||
@property
|
||||
@ -576,7 +650,8 @@ class PyLammps(object):
|
||||
:getter: Returns a list of dumps that are currently active in this LAMMPS instance
|
||||
:type: list
|
||||
"""
|
||||
output = self.info("dumps")
|
||||
output = self.lmp_info("dumps")
|
||||
output = output[output.index("Dump information:")+1:]
|
||||
return self._parse_element_list(output)
|
||||
|
||||
@property
|
||||
@ -587,7 +662,8 @@ class PyLammps(object):
|
||||
:getter: Returns a list of fixes that are currently active in this LAMMPS instance
|
||||
:type: list
|
||||
"""
|
||||
output = self.info("fixes")
|
||||
output = self.lmp_info("fixes")
|
||||
output = output[output.index("Fix information:")+1:]
|
||||
return self._parse_element_list(output)
|
||||
|
||||
@property
|
||||
@ -598,7 +674,8 @@ class PyLammps(object):
|
||||
:getter: Returns a list of atom groups that are currently active in this LAMMPS instance
|
||||
:type: list
|
||||
"""
|
||||
output = self.info("groups")
|
||||
output = self.lmp_info("groups")
|
||||
output = output[output.index("Group information:")+1:]
|
||||
return self._parse_groups(output)
|
||||
|
||||
@property
|
||||
@ -609,11 +686,12 @@ class PyLammps(object):
|
||||
:getter: Returns a dictionary of all variables that are defined in this LAMMPS instance
|
||||
:type: dict
|
||||
"""
|
||||
output = self.info("variables")
|
||||
vars = {}
|
||||
output = self.lmp_info("variables")
|
||||
output = output[output.index("Variable information:")+1:]
|
||||
variables = {}
|
||||
for v in self._parse_element_list(output):
|
||||
vars[v['name']] = Variable(self, v['name'], v['style'], v['def'])
|
||||
return vars
|
||||
variables[v['name']] = Variable(self, v['name'], v['style'], v['def'])
|
||||
return variables
|
||||
|
||||
def eval(self, expr):
|
||||
"""
|
||||
@ -638,10 +716,9 @@ class PyLammps(object):
|
||||
return [x.strip() for x in value.split('=')]
|
||||
|
||||
def _parse_info_system(self, output):
|
||||
lines = output[5:-2]
|
||||
system = {}
|
||||
|
||||
for line in lines:
|
||||
for line in output:
|
||||
if line.startswith("Units"):
|
||||
system['units'] = self._get_pair(line)[1]
|
||||
elif line.startswith("Atom style"):
|
||||
@ -699,10 +776,9 @@ class PyLammps(object):
|
||||
return system
|
||||
|
||||
def _parse_info_communication(self, output):
|
||||
lines = output[5:-3]
|
||||
comm = {}
|
||||
|
||||
for line in lines:
|
||||
for line in output:
|
||||
if line.startswith("MPI library"):
|
||||
comm['mpi_version'] = line.split(':')[1].strip()
|
||||
elif line.startswith("Comm style"):
|
||||
@ -720,10 +796,10 @@ class PyLammps(object):
|
||||
return comm
|
||||
|
||||
def _parse_element_list(self, output):
|
||||
lines = output[5:-3]
|
||||
elements = []
|
||||
|
||||
for line in lines:
|
||||
for line in output:
|
||||
if not line or (":" not in line): continue
|
||||
element_info = self._split_values(line.split(':')[1].strip())
|
||||
element = {'name': element_info[0]}
|
||||
for key, value in [self._get_pair(x) for x in element_info[1:]]:
|
||||
@ -732,11 +808,10 @@ class PyLammps(object):
|
||||
return elements
|
||||
|
||||
def _parse_groups(self, output):
|
||||
lines = output[5:-3]
|
||||
groups = []
|
||||
group_pattern = re.compile(r"(?P<name>.+) \((?P<type>.+)\)")
|
||||
|
||||
for line in lines:
|
||||
for line in output:
|
||||
m = group_pattern.match(line.split(':')[1].strip())
|
||||
group = {'name': m.group('name'), 'type': m.group('type')}
|
||||
groups.append(group)
|
||||
@ -747,7 +822,7 @@ class PyLammps(object):
|
||||
return self.__getattr__("print")(s)
|
||||
|
||||
def __dir__(self):
|
||||
return ['angle_coeff', 'angle_style', 'atom_modify', 'atom_style', 'atom_style',
|
||||
return sorted(set(['angle_coeff', 'angle_style', 'atom_modify', 'atom_style', 'atom_style',
|
||||
'bond_coeff', 'bond_style', 'boundary', 'change_box', 'communicate', 'compute',
|
||||
'create_atoms', 'create_box', 'delete_atoms', 'delete_bonds', 'dielectric',
|
||||
'dihedral_coeff', 'dihedral_style', 'dimension', 'dump', 'fix', 'fix_modify',
|
||||
@ -757,7 +832,16 @@ class PyLammps(object):
|
||||
'pair_style', 'processors', 'read', 'read_data', 'read_restart', 'region',
|
||||
'replicate', 'reset_timestep', 'restart', 'run', 'run_style', 'thermo',
|
||||
'thermo_modify', 'thermo_style', 'timestep', 'undump', 'unfix', 'units',
|
||||
'variable', 'velocity', 'write_restart']
|
||||
'variable', 'velocity', 'write_restart'] + self.lmp.available_styles("command")))
|
||||
|
||||
def lmp_info(self, s):
|
||||
# skip anything before and after Info-Info-Info
|
||||
# also skip timestamp line
|
||||
output = self.__getattr__("info")(s)
|
||||
indices = [index for index, line in enumerate(output) if line.startswith("Info-Info-Info-Info")]
|
||||
start = indices[0]
|
||||
end = indices[1]
|
||||
return [line for line in output[start+2:end] if line]
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""
|
||||
@ -773,10 +857,12 @@ class PyLammps(object):
|
||||
"""
|
||||
def handler(*args, **kwargs):
|
||||
cmd_args = [name] + [str(x) for x in args]
|
||||
self.lmp.flush_buffers()
|
||||
|
||||
with OutputCapture() as capture:
|
||||
cmd = ' '.join(cmd_args)
|
||||
self.command(cmd)
|
||||
self.lmp.flush_buffers()
|
||||
output = capture.output
|
||||
|
||||
comm = self.lmp.get_mpi_comm()
|
||||
|
||||
@ -213,8 +213,7 @@ void Error::one(const std::string &file, int line, const std::string &str)
|
||||
|
||||
throw LAMMPSAbortException(mesg, world);
|
||||
#else
|
||||
if (screen) fflush(screen);
|
||||
if (logfile) fflush(logfile);
|
||||
utils::flush_buffers(lmp);
|
||||
KokkosLMP::finalize();
|
||||
MPI_Abort(world,1);
|
||||
exit(1); // to trick "smart" compilers into believing this does not return
|
||||
|
||||
@ -5439,6 +5439,21 @@ void lammps_fix_external_set_vector(void *handle, const char *id, int idx, doubl
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/** Flush output buffers
|
||||
|
||||
\verbatim embed:rst
|
||||
This function can be used to force output to be written to screen and logfiles
|
||||
to simplify capturing output from LAMMPS library calls.
|
||||
\endverbatim
|
||||
*
|
||||
* \param handle pointer to a previously created LAMMPS instance cast to ``void *``.
|
||||
*/
|
||||
void lammps_flush_buffers(void *handle) {
|
||||
utils::flush_buffers((LAMMPS *) handle);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/** Free memory buffer allocated by LAMMPS.
|
||||
*
|
||||
\verbatim embed:rst
|
||||
|
||||
@ -246,6 +246,8 @@ void lammps_fix_external_set_virial_peratom(void *handle, const char *id, double
|
||||
void lammps_fix_external_set_vector_length(void *handle, const char *id, int len);
|
||||
void lammps_fix_external_set_vector(void *handle, const char *id, int idx, double val);
|
||||
|
||||
void lammps_flush_buffers(void *ptr);
|
||||
|
||||
void lammps_free(void *ptr);
|
||||
|
||||
int lammps_is_running(void *handle);
|
||||
|
||||
@ -375,8 +375,7 @@ void Thermo::compute(int flag)
|
||||
|
||||
if (me == 0) {
|
||||
utils::logmesg(lmp,line);
|
||||
if (screen && flushflag) fflush(screen);
|
||||
if (logfile && flushflag) fflush(logfile);
|
||||
if (flushflag) utils::flush_buffers(lmp);
|
||||
}
|
||||
|
||||
// set to 1, so that subsequent invocations of CPU time will be non-zero
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include "text_file_reader.h"
|
||||
#include "tokenizer.h"
|
||||
#include "update.h"
|
||||
#include "universe.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
@ -138,6 +139,14 @@ void utils::fmtargs_logmesg(LAMMPS *lmp, fmt::string_view format, fmt::format_ar
|
||||
}
|
||||
}
|
||||
|
||||
void utils::flush_buffers(LAMMPS *lmp)
|
||||
{
|
||||
if (lmp->screen) fflush(lmp->screen);
|
||||
if (lmp->logfile) fflush(lmp->logfile);
|
||||
if (lmp->universe->uscreen) fflush(lmp->universe->uscreen);
|
||||
if (lmp->universe->ulogfile) fflush(lmp->universe->ulogfile);
|
||||
}
|
||||
|
||||
/* define this here, so we won't have to include the headers
|
||||
everywhere and utils.h will more likely be included anyway. */
|
||||
|
||||
|
||||
@ -74,6 +74,14 @@ namespace utils {
|
||||
|
||||
void logmesg(LAMMPS *lmp, const std::string &mesg);
|
||||
|
||||
/*! Flush output buffers
|
||||
*
|
||||
* This function calls fflush on screen and logfile FILE pointers
|
||||
* if available
|
||||
*/
|
||||
|
||||
void flush_buffers(LAMMPS *lmp);
|
||||
|
||||
/*! Return a string representing the current system error status
|
||||
*
|
||||
* This is a wrapper around calling strerror(errno).
|
||||
|
||||
@ -156,6 +156,8 @@ extern int lammps_is_running(void *handle);
|
||||
extern void lammps_force_timeout(void *handle);
|
||||
extern int lammps_has_error(void *handle);
|
||||
extern int lammps_get_last_error_message(void *handle, char *buffer, int buf_size);
|
||||
|
||||
extern void lammps_flush_buffers(void *ptr);
|
||||
%}
|
||||
|
||||
enum _LMP_DATATYPE_CONST {
|
||||
@ -287,4 +289,6 @@ extern void lammps_force_timeout(void *handle);
|
||||
extern int lammps_has_error(void *handle);
|
||||
extern int lammps_get_last_error_message(void *handle, char *buffer, int buf_size);
|
||||
|
||||
/* last revised on 21 July 2021 */
|
||||
extern void lammps_flush_buffers(void *ptr);
|
||||
|
||||
/* last revised on 4 February 2022 */
|
||||
|
||||
@ -98,14 +98,10 @@ if(Python_EXECUTABLE)
|
||||
WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
|
||||
set_tests_properties(PythonCapabilities PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}")
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
message(STATUS "Skipping Tests for PyLammps Module: not yet ported to Windows")
|
||||
else()
|
||||
add_test(NAME PythonPyLammps
|
||||
COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-pylammps.py -v
|
||||
WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
|
||||
set_tests_properties(PythonPyLammps PROPERTIES ENVIRONMENT "${PYTHON_TEST_ENVIRONMENT}")
|
||||
endif()
|
||||
|
||||
add_test(NAME PythonFormats
|
||||
COMMAND ${PYTHON_TEST_RUNNER} ${CMAKE_CURRENT_SOURCE_DIR}/python-formats.py -v
|
||||
|
||||
@ -1,6 +1,13 @@
|
||||
import sys,os,unittest
|
||||
import os,unittest
|
||||
from lammps import PyLammps
|
||||
|
||||
try:
|
||||
import numpy
|
||||
NUMPY_INSTALLED = True
|
||||
except ImportError:
|
||||
NUMPY_INSTALLED = False
|
||||
|
||||
@unittest.skipIf(not NUMPY_INSTALLED, "numpy is not available")
|
||||
class PythonPyLammps(unittest.TestCase):
|
||||
def setUp(self):
|
||||
machine = None
|
||||
@ -49,8 +56,8 @@ class PythonPyLammps(unittest.TestCase):
|
||||
self.assertEqual(self.pylmp.lmp.create_atoms(2, id=None, type=types, x=x), 2)
|
||||
self.assertEqual(self.pylmp.system.natoms, 2)
|
||||
self.assertEqual(len(self.pylmp.atoms), 2)
|
||||
self.assertEqual(self.pylmp.atoms[0].position, tuple(x[0:3]))
|
||||
self.assertEqual(self.pylmp.atoms[1].position, tuple(x[3:6]))
|
||||
numpy.testing.assert_array_equal(self.pylmp.atoms[0].position, tuple(x[0:3]))
|
||||
numpy.testing.assert_array_equal(self.pylmp.atoms[1].position, tuple(x[3:6]))
|
||||
self.assertEqual(self.pylmp.last_run, None)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user