from numpy import genfromtxt, fromstring, reshape, zeros, sum as nsum
from urllib import request as urllibr
from urllib import error as urlerror
from mango.io import read_data, separater
from mango.constants import c
[docs]def initpos(lj_num, sigma, location=None, boxsize=0, xyz=False):
"""
Get the positions of particles.
Also can collect magnetisations and momentums
Can be user specified with location or downloaded using urllj
Downloaded positions from standard LJ stable structures
An (extended) xyz file can be specified the last frame in the file
will be used
Parameters
----------
lj_num: int
Number of molecules
sigma: float
distance between particle centres
location: string
location of file to load
boxsize: float
periodic boxsize (only required for 2 particle periodic systems)
"""
if isinstance(location, str):
molecules, response, xyz = posfile(location, sigma)
elif lj_num == 1:
response = zeros(3)
elif lj_num == 2:
response = twoparticlesinabox(boxsize, sigma)
elif lj_num > 150:
c.Error("{}{}{}".format("F This is only setup for under 150 particles\n",
"for larger systems please specify a position file.\n",
"Larger structures may be available at http://doye.chem.ox.ac.uk/jon/structures/LJ/"))
else:
# TODO proper sigma conversion
response = urllj(lj_num) * sigma[:, None]
return separater(response), xyz
[docs]def twoparticlesinabox(boxsize, sigma):
"""
Set location of 2 particles.
put two particles next to each other
"""
response = zeros((2, 3))
avdist = nsum(sigma) / 2
if boxsize >= nsum(sigma):
response[0, :] = [-avdist / 2, 0, 0]
response[1, :] = [avdist / 2, 0, 0]
else:
response[0, :] = [-boxsize / 8, 0, 0]
response[1, :] = [boxsize / 8, 0, 0]
return response
[docs]def posfile(location, sigma, xyz=False, com=0):
"""
Open position file.
Reads first two lines to check
if xyz open xyz otherwise read as unscaled coordinates
"""
lines = []
try:
with open(location, "r") as file:
for n, l in enumerate(file):
if l.startswith(("#", "\n")):
com += 1
elif n < (2 + com):
lines += [l.split()]
else:
break
except OSError:
c.Error(f"F Unable to find location file '{location}'")
if len(lines[0]) != len(lines[1]):
# TODO more secure xyz check (check lines[0][0] is int?)
molecules, response = read_data(location.rsplit(".", 1)[0], "xyz").xyzread()
response = response[-1]
xyz = True
else:
# TODO Currently this doesn't check if the file is prescaled. XYZ is the safe option in this case
# TODO Catch errors here from genfromtxt
response = genfromtxt(location) * sigma[:, None]
molecules = None
return molecules, response, xyz
[docs]def urllj(lj_num, url="http://doye.chem.ox.ac.uk/jon/structures/LJ/points/{}"):
"""
Download lj configuration.
Default url is http://doye.chem.ox.ac.uk/jon/structures/LJ/
Parameters
----------
lj_num: int
Number of molecules
url: str
url with formatting {} for lj_num
"""
try:
url = url.format(lj_num)
response = urllibr.urlopen(url).read().decode('utf-8')
response = fromstring(" ".join(response.split("\n")), sep=" ")
response = reshape(response, (lj_num, 3))
except urlerror.HTTPError:
c.Error("F Not found online for {} molecules".format(lj_num))
except urlerror.URLError:
c.Error("F Internet Connection Error, Particle locations cannot be downloaded")
else:
return response
if __name__ == '__main__':
pass