So LAMMPS (http://lammps.sandia.gov/) has a python interface which I have been trying to use within Julia, with some success. However, I had two points I wanted to query the community about.
First, when I wish to access the positions of the atoms within the environment, I run the following commands:
using PyCall
@pyimport lammps
@pyimport numpy.ctypeslib as ctlib
lmp = lammps.lammps()
lmp[:file]("setup.lammps") # raw lammps scripting set up file
# n = number of atoms, something I would set beforehand
Xobj = @pycall ctlib.as_array(lmp[:extract_atom]("x",3)[:contents],shape=(n,3))::Any
X = unsafe_wrap(Array{Float64,2}, Ptr{Float64}(Xobj[:__array_interface__]["data"][1]), reverse(Xobj[:__array_interface__]["shape"]))
Fobj = @pycall ctlib.as_array(lmp[:extract_atom]("f",3)[:contents],shape=(n,3))::Any
F = unsafe_wrap(Array{Float64,2}, Ptr{Float64}(Fobj[:__array_interface__]["data"][1]), reverse(Fobj[:__array_interface__]["shape"]))
At this point I have (3,n) Julia arrays which gives me access to the underlying positions and forces of the atoms, X
and F
. Clearly, it takes two commands for each such array. Is there a way to condense this down to single command? Is there a way to do this more efficiently?
Second, suppose I want to do a very elementary simulation, running the overdamped langevin problem, as
# set nsteps number of time steps, Dt the step size, and kBT the temperature
for j =1:nsteps
X.+= Dt.*F .+ sqrt(2. * kBT * Dt) .* randn(3,n)
lmp[:command]("run 1 pre yes post no") # forces the lammps environment to update forces as atoms move
# other commands go here
end
While this works, I find that the analogous code within python is about twice as fast. Are there any obvious mistakes and/or ways to get back the Python speed?