a few new lib interface methods
This commit is contained in:
@ -80,12 +80,59 @@ lmp.commands_list(cmds)
|
||||
# initial thermo should be same as step 20
|
||||
|
||||
natoms = lmp.get_natoms()
|
||||
type = natoms*[1]
|
||||
atype = natoms*[1]
|
||||
|
||||
lmp.command("delete_atoms group all");
|
||||
lmp.create_atoms(natoms,None,type,x,v);
|
||||
lmp.create_atoms(natoms,None,atype,x,v);
|
||||
lmp.command("run 10");
|
||||
|
||||
############
|
||||
# test of new gather/scatter and box extract/reset methods
|
||||
# can try this in parallel and with/without atom_modify sort enabled
|
||||
|
||||
lmp.command("write_dump all custom tmp.simple id type x y z fx fy fz");
|
||||
|
||||
x = lmp.gather_atoms("x",1,3)
|
||||
f = lmp.gather_atoms("f",1,3)
|
||||
|
||||
if me == 0: print("Gather XF:",x[3],x[9],f[3],f[9])
|
||||
|
||||
ids = lmp.gather_atoms_concat("id",0,1)
|
||||
x = lmp.gather_atoms_concat("x",1,3)
|
||||
f = lmp.gather_atoms_concat("f",1,3)
|
||||
|
||||
if me == 0: print("Gather concat XF:",ids[0],ids[1],x[0],x[3],f[0],f[3])
|
||||
|
||||
ids = (2*ctypes.c_int)()
|
||||
ids[0] = 2
|
||||
ids[1] = 4
|
||||
x = lmp.gather_atoms_subset("x",1,3,2,ids)
|
||||
f = lmp.gather_atoms_subset("f",1,3,2,ids)
|
||||
|
||||
if me == 0: print("Gather subset XF:",x[0],x[3],f[0],f[3])
|
||||
|
||||
x[0] = -1.0
|
||||
x[1] = 0.0
|
||||
x[2] = 0.0
|
||||
x[3] = -2.0
|
||||
x[4] = 0.0
|
||||
x[5] = 0.0
|
||||
ids[0] = 100
|
||||
ids[1] = 200
|
||||
lmp.scatter_atoms_subset("x",1,3,2,ids,x)
|
||||
|
||||
x = lmp.gather_atoms("x",1,3)
|
||||
if me == 0: print("Gather post scatter subset:",
|
||||
x[3],x[9],x[297],x[298],x[299],x[597],x[598],x[599])
|
||||
|
||||
boxlo,boxhi,xy,yz,xz,periodicity,box_change = lmp.extract_box()
|
||||
if me == 0: print("Box info",boxlo,boxhi,xy,yz,xz,periodicity,box_change)
|
||||
|
||||
lmp.reset_box([0,0,0],[10,10,8],0,0,0)
|
||||
|
||||
boxlo,boxhi,xy,yz,xz,periodicity,box_change = lmp.extract_box()
|
||||
if me == 0: print("Box info",boxlo,boxhi,xy,yz,xz,periodicity,box_change)
|
||||
|
||||
# uncomment if running in parallel via Pypar
|
||||
#print("Proc %d out of %d procs has" % (me,nprocs), lmp)
|
||||
|
||||
|
||||
156
python/lammps.py
156
python/lammps.py
@ -94,6 +94,39 @@ class lammps(object):
|
||||
if not name: self.lib = CDLL("liblammps.so",RTLD_GLOBAL)
|
||||
else: self.lib = CDLL("liblammps_%s.so" % name,RTLD_GLOBAL)
|
||||
|
||||
# define ctypes API for each library method
|
||||
# NOTE: should add one of these for each lib function
|
||||
|
||||
self.lib.lammps_extract_box.argtypes = \
|
||||
[c_void_p,POINTER(c_double),POINTER(c_double),
|
||||
POINTER(c_double),POINTER(c_double),POINTER(c_double),
|
||||
POINTER(c_int),POINTER(c_int)]
|
||||
self.lib.lammps_extract_box.restype = None
|
||||
|
||||
self.lib.lammps_reset_box.argtypes = \
|
||||
[c_void_p,POINTER(c_double),POINTER(c_double),c_double,c_double,c_double]
|
||||
self.lib.lammps_reset_box.restype = None
|
||||
|
||||
self.lib.lammps_gather_atoms.argtypes = \
|
||||
[c_void_p,c_char_p,c_int,c_int,c_void_p]
|
||||
self.lib.lammps_gather_atoms.restype = None
|
||||
|
||||
self.lib.lammps_gather_atoms_concat.argtypes = \
|
||||
[c_void_p,c_char_p,c_int,c_int,c_void_p]
|
||||
self.lib.lammps_gather_atoms_concat.restype = None
|
||||
|
||||
self.lib.lammps_gather_atoms_subset.argtypes = \
|
||||
[c_void_p,c_char_p,c_int,c_int,c_int,POINTER(c_int),c_void_p]
|
||||
self.lib.lammps_gather_atoms_subset.restype = None
|
||||
|
||||
self.lib.lammps_scatter_atoms.argtypes = \
|
||||
[c_void_p,c_char_p,c_int,c_int,c_void_p]
|
||||
self.lib.lammps_scatter_atoms.restype = None
|
||||
|
||||
self.lib.lammps_scatter_atoms_subset.argtypes = \
|
||||
[c_void_p,c_char_p,c_int,c_int,c_int,POINTER(c_int),c_void_p]
|
||||
self.lib.lammps_scatter_atoms_subset.restype = None
|
||||
|
||||
# if no ptr provided, create an instance of LAMMPS
|
||||
# don't know how to pass an MPI communicator from PyPar
|
||||
# but we can pass an MPI communicator from mpi4py v2.0.0 and later
|
||||
@ -177,6 +210,8 @@ class lammps(object):
|
||||
self.c_tagint = get_ctypes_int(self.extract_setting("tagint"))
|
||||
self.c_imageint = get_ctypes_int(self.extract_setting("imageint"))
|
||||
|
||||
# shut-down LAMMPS instance
|
||||
|
||||
def __del__(self):
|
||||
if self.lmp and self.opened:
|
||||
self.lib.lammps_close(self.lmp)
|
||||
@ -219,10 +254,16 @@ class lammps(object):
|
||||
# send a string of commands
|
||||
|
||||
def commands_string(self,multicmd):
|
||||
if type(multicmd) is str:
|
||||
multicmd = multicmd.encode()
|
||||
if type(multicmd) is str: multicmd = multicmd.encode()
|
||||
self.lib.lammps_commands_string(self.lmp,c_char_p(multicmd))
|
||||
|
||||
# extract lammps type byte sizes
|
||||
|
||||
def extract_setting(self, name):
|
||||
if name: name = name.encode()
|
||||
self.lib.lammps_extract_atom.restype = c_int
|
||||
return int(self.lib.lammps_extract_setting(self.lmp,name))
|
||||
|
||||
# extract global info
|
||||
|
||||
def extract_global(self,name,type):
|
||||
@ -235,8 +276,35 @@ class lammps(object):
|
||||
ptr = self.lib.lammps_extract_global(self.lmp,name)
|
||||
return ptr[0]
|
||||
|
||||
# extract global info
|
||||
|
||||
def extract_box(self):
|
||||
boxlo = (3*c_double)()
|
||||
boxhi = (3*c_double)()
|
||||
xy = c_double()
|
||||
yz = c_double()
|
||||
xz = c_double()
|
||||
periodicity = (3*c_int)()
|
||||
box_change = c_int()
|
||||
|
||||
self.lib.lammps_extract_box(self.lmp,boxlo,boxhi,
|
||||
byref(xy),byref(yz),byref(xz),
|
||||
periodicity,byref(box_change))
|
||||
|
||||
boxlo = boxlo[:3]
|
||||
boxhi = boxhi[:3]
|
||||
xy = xy.value
|
||||
yz = yz.value
|
||||
xz = xz.value
|
||||
periodicity = periodicity[:3]
|
||||
box_change = box_change.value
|
||||
|
||||
return boxlo,boxhi,xy,yz,xz,periodicity,box_change
|
||||
|
||||
# extract per-atom info
|
||||
|
||||
# NOTE: need to insure are converting to/from correct Python type
|
||||
# e.g. for Python list or NumPy or ctypes
|
||||
|
||||
def extract_atom(self,name,type):
|
||||
if name: name = name.encode()
|
||||
if type == 0:
|
||||
@ -250,14 +318,7 @@ class lammps(object):
|
||||
else: return None
|
||||
ptr = self.lib.lammps_extract_atom(self.lmp,name)
|
||||
return ptr
|
||||
|
||||
# extract lammps type byte sizes
|
||||
|
||||
def extract_setting(self, name):
|
||||
if name: name = name.encode()
|
||||
self.lib.lammps_extract_atom.restype = c_int
|
||||
return int(self.lib.lammps_extract_setting(self.lmp,name))
|
||||
|
||||
|
||||
@property
|
||||
def numpy(self):
|
||||
if not self._numpy:
|
||||
@ -378,15 +439,6 @@ class lammps(object):
|
||||
return result
|
||||
return None
|
||||
|
||||
# set variable value
|
||||
# value is converted to string
|
||||
# returns 0 for success, -1 if failed
|
||||
|
||||
def set_variable(self,name,value):
|
||||
if name: name = name.encode()
|
||||
if value: value = str(value).encode()
|
||||
return self.lib.lammps_set_variable(self.lmp,name,value)
|
||||
|
||||
# return current value of thermo keyword
|
||||
|
||||
def get_thermo(self,name):
|
||||
@ -399,14 +451,30 @@ class lammps(object):
|
||||
def get_natoms(self):
|
||||
return self.lib.lammps_get_natoms(self.lmp)
|
||||
|
||||
# return vector of atom properties gathered across procs, ordered by atom ID
|
||||
# set variable value
|
||||
# value is converted to string
|
||||
# returns 0 for success, -1 if failed
|
||||
|
||||
def set_variable(self,name,value):
|
||||
if name: name = name.encode()
|
||||
if value: value = str(value).encode()
|
||||
return self.lib.lammps_set_variable(self.lmp,name,value)
|
||||
|
||||
# reset simulation box size
|
||||
|
||||
def reset_box(self,boxlo,boxhi,xy,yz,xz):
|
||||
cboxlo = (3*c_double)(*boxlo)
|
||||
cboxhi = (3*c_double)(*boxhi)
|
||||
self.lib.lammps_reset_box(self.lmp,cboxlo,cboxhi,xy,yz,xz)
|
||||
|
||||
# return vector of atom properties gathered across procs
|
||||
# 3 variants to match src/library.cpp
|
||||
# name = atom property recognized by LAMMPS in atom->extract()
|
||||
# type = 0 for integer values, 1 for double values
|
||||
# count = number of per-atom valus, 1 for type or charge, 3 for x or f
|
||||
# returned data is a 1d vector - doc how it is ordered?
|
||||
# NOTE: how could we insure are converting to correct Python type
|
||||
# e.g. for Python list or NumPy, etc
|
||||
# ditto for extract_atom() above
|
||||
# NOTE: need to insure are converting to/from correct Python type
|
||||
# e.g. for Python list or NumPy or ctypes
|
||||
|
||||
def gather_atoms(self,name,type,count):
|
||||
if name: name = name.encode()
|
||||
@ -419,19 +487,47 @@ class lammps(object):
|
||||
self.lib.lammps_gather_atoms(self.lmp,name,type,count,data)
|
||||
else: return None
|
||||
return data
|
||||
|
||||
def gather_atoms_concat(self,name,type,count):
|
||||
if name: name = name.encode()
|
||||
natoms = self.lib.lammps_get_natoms(self.lmp)
|
||||
if type == 0:
|
||||
data = ((count*natoms)*c_int)()
|
||||
self.lib.lammps_gather_atoms_concat(self.lmp,name,type,count,data)
|
||||
elif type == 1:
|
||||
data = ((count*natoms)*c_double)()
|
||||
self.lib.lammps_gather_atoms_concat(self.lmp,name,type,count,data)
|
||||
else: return None
|
||||
return data
|
||||
|
||||
# scatter vector of atom properties across procs, ordered by atom ID
|
||||
def gather_atoms_subset(self,name,type,count,ndata,ids):
|
||||
if name: name = name.encode()
|
||||
if type == 0:
|
||||
data = ((count*ndata)*c_int)()
|
||||
self.lib.lammps_gather_atoms_subset(self.lmp,name,type,count,ndata,ids,data)
|
||||
elif type == 1:
|
||||
data = ((count*ndata)*c_double)()
|
||||
self.lib.lammps_gather_atoms_subset(self.lmp,name,type,count,ndata,ids,data)
|
||||
else: return None
|
||||
return data
|
||||
|
||||
# scatter vector of atom properties across procs
|
||||
# 2 variants to match src/library.cpp
|
||||
# name = atom property recognized by LAMMPS in atom->extract()
|
||||
# type = 0 for integer values, 1 for double values
|
||||
# count = number of per-atom valus, 1 for type or charge, 3 for x or f
|
||||
# assume data is of correct type and length, as created by gather_atoms()
|
||||
# NOTE: how could we insure are passing correct type to LAMMPS
|
||||
# e.g. for Python list or NumPy, etc
|
||||
|
||||
# NOTE: need to insure are converting to/from correct Python type
|
||||
# e.g. for Python list or NumPy or ctypes
|
||||
|
||||
def scatter_atoms(self,name,type,count,data):
|
||||
if name: name = name.encode()
|
||||
self.lib.lammps_scatter_atoms(self.lmp,name,type,count,data)
|
||||
|
||||
def scatter_atoms_subset(self,name,type,count,ndata,ids,data):
|
||||
if name: name = name.encode()
|
||||
self.lib.lammps_scatter_atoms_subset(self.lmp,name,type,count,ndata,ids,data)
|
||||
|
||||
# create N atoms on all procs
|
||||
# N = global number of atoms
|
||||
# id = ID of each atom (optional, can be None)
|
||||
@ -457,8 +553,8 @@ class lammps(object):
|
||||
|
||||
type_lmp = (c_int * n)()
|
||||
type_lmp[:] = type
|
||||
self.lib.lammps_create_atoms(self.lmp,n,id_lmp,type_lmp,x,v,image_lmp,shrinkexceed)
|
||||
|
||||
self.lib.lammps_create_atoms(self.lmp,n,id_lmp,type_lmp,x,v,image_lmp,
|
||||
shrinkexceed)
|
||||
|
||||
@property
|
||||
def uses_exceptions(self):
|
||||
|
||||
Reference in New Issue
Block a user