Files
LPP/src/patch.py
danielque 50efb8ee82 increase python 2 - 3 compatibility
python 2 vs 3 imports
2023-08-10 16:44:58 +02:00

1368 lines
48 KiB
Python

# Pizza.py toolkit, www.cs.sandia.gov/~sjplimp/pizza.html
# Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
#
# Copyright (2005) Sandia Corporation. Under the terms of Contract
# DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
# certain rights in this software. This software is distributed under
# the GNU General Public License.
# patch tool
# Imports and external programs
from __future__ import print_function, absolute_import
from math import sqrt,pi,cos,sin
from data import data
oneline = "Create patchy Lennard-Jones particles for LAMMPS input"
docstr = """
p = patch(vfrac) setup box with a specified volume fraction
p = patch(vfrac,1,1,2) x,y,z = aspect ratio of box (def = 1,1,1)
p.seed = 48379 set random # seed (def = 12345)
p.randomized = 0 1 = choose next particle randomly, 0 = as generated
p.dim = 2 set dimension of created box (def = 3)
p.blen = 0.97 set length of tether bonds (def = 0.97)
p.dmin = 1.02 set min r from i-1 to i+1 tether site (def = 1.02)
p.lattice = [Nx,Ny,Nz] generate Nx by Ny by Nz lattice of particles
if lattice is set, Nx*Ny*Nz must equal N for build
lattice = [0,0,0] = generate N particles randomly, default
p.build(100,"hex2",1,2,3) create 100 "hex2" particles with types 1,2,3
can be invoked multiple times
keywords:
c60hex2: diam,1,2,3 = C-60 with 2 hex patches and ctr part, types 1,2,3
hex2: diam,1,2 = one large particle with 2 7-mer hex patches, types 1,2
hex4: diam,1,2 = one large particle with 4 7-mer hex patches, types 1,2
ring: diam,N,1,2 = one large part with equatorial ring of N, types 1,2
ball: diam,m1,m2,1,2,3 = large ball with m12-len tethers, types 1,2,3
tri5: 1,2 = 3-layer 5-size hollow tri, types 1,2
rod: N,m1,m2,1,2,3 = N-length rod with m12-len tethers, types 1,2,3
tri: N,m1,m2,m3,1,2,3,4 = N-size tri with m123-len tethers, types 1-4
hex: m1,m2,m3,m4,m5,m6,1,2,3,4,5,6,7 = 7-atom hex with m-len tethers, t 1-7
dimer: r,1 = two particles r apart, type 1, no bond
star2d: N,r,1 = 2d star of length N (odd), beads r apart, type 1, no bonds
box2d: N,M,r,1 = 2d NxM box, beads r apart, type 1, no bonds
tritet: A,m = 4-tri tet with edge length A, tri type m
tribox: Alo,Ahi,Blo,Bhi,Clo,Chi,m = 12-tri box with side lengths A,B,C & m
linebox: Alo,Ahi,Blo,Bhi,m = 4-line 2d rectangle with random side lengths
from Alo to Ahi and Blo to Bhi, line type m
linetri: Alo,Ahi,Blo,Bhi,m = 3-line 2d triangle with random base
from Alo to Ahi and height Blo to Bhi, type m
p.write("data.patch") write out system to LAMMPS data file
"""
# History
# 8/05, Steve Plimpton (SNL): original version
# ToDo list
# Variables
# vfrac = desired volume fraction
# x,y,z = aspect ratio of box (def = 1,1,1)
# seed = random seed
# molecules = list of atoms, grouped by molecule
# Class definition
class patch:
# --------------------------------------------------------------------
def __init__(self,vfrac,*list):
self.vfrac = vfrac
self.xaspect = self.yaspect = self.zaspect = 1.0
if len(list):
self.xaspect = list[0]
self.yaspect = list[1]
self.zaspect = list[2]
self.seed = 12345
self.randomized = 1
self.dim = 3
self.molecules = []
self.volume = 0
self.blen = 0.97
self.dmin = 1.02
self.lattice = [0,0,0]
self.style = "molecular"
# --------------------------------------------------------------------
# call style method with extra args
# adds to volume and atom list
# reset self.style for lines and triangles
def build(self,n,style,*types):
if style == "linebox" or style == "linetri": self.style = "line"
if style == "tritet" or style == "tribox": self.style = "tri"
cmd = "atoms,bonds,tris,segments,volume = self.%s(*types)" % style
for i in range(n):
ldict = {'i':i,'self':self,'types':types}
exec(cmd,globals(),ldict)
atoms = ldict['atoms']
bonds = ldict['bonds']
tris = ldict['tris']
segments = ldict['segments']
volume = ldict['volume']
self.molecules.append([atoms,bonds,tris,segments])
self.volume += volume
# --------------------------------------------------------------------
# create the atom coords in a scaled-size box of correct dimension
# write them to LAMMPS data file
def write(self,file):
if self.dim == 3: self.write3d(file)
else: self.write2d(file)
# --------------------------------------------------------------------
# write a 3d simulation to data file
def write3d(self,file):
volume = self.volume/self.vfrac
prd = pow(volume/self.xaspect/self.yaspect/self.zaspect,1.0/3.0)
self.xprd = self.xaspect * prd
self.xlo = -self.xprd/2.0
self.xhi = self.xprd/2.0
self.yprd = self.yaspect * prd
self.ylo = -self.yprd/2.0
self.yhi = self.yprd/2.0
self.zprd = self.zaspect * prd
self.zlo = -self.zprd/2.0
self.zhi = self.zprd/2.0
if self.lattice[0] or self.lattice[1] or self.lattice[2]:
latflag = 1
if self.lattice[0]*self.lattice[1]*self.lattice[2] != \
len(self.molecules):
raise Exception("lattice inconsistent with # of molecules")
else: latflag = 0
idatom = idbond = idtri = idmol = 0
atoms = []
bonds = []
tris = []
xp = 3*[0]
yp = 3*[0]
zp = 3*[0]
while self.molecules:
if self.randomized: i = int(self.random()*len(self.molecules))
else: i = 0
molecule = self.molecules.pop(i)
idmol += 1
triples = []
# xp[3],yp[3],zp[3] = randomly oriented, normalized basis vectors
# xp is in random direction
# yp is random dir crossed into xp
# zp is xp crossed into yp
xp[0] = self.random() - 0.5
xp[1] = self.random() - 0.5
xp[2] = self.random() - 0.5
r = sqrt(xp[0]*xp[0] + xp[1]*xp[1] + xp[2]*xp[2])
xp[0],xp[1],xp[2] = xp[0]/r,xp[1]/r,xp[2]/r
r0 = self.random() - 0.5
r1 = self.random() - 0.5
r2 = self.random() - 0.5
yp[0] = r1*xp[2] - r2*xp[1]
yp[1] = r2*xp[0] - r0*xp[2]
yp[2] = r0*xp[1] - r1*xp[0]
r = sqrt(yp[0]*yp[0] + yp[1]*yp[1] + yp[2]*yp[2])
yp[0],yp[1],yp[2] = yp[0]/r,yp[1]/r,yp[2]/r
zp[0] = xp[1]*yp[2] - xp[2]*yp[1]
zp[1] = xp[2]*yp[0] - xp[0]*yp[2]
zp[2] = xp[0]*yp[1] - xp[1]*yp[0]
r = sqrt(zp[0]*zp[0] + zp[1]*zp[1] + zp[2]*zp[2])
zp[0],zp[1],zp[2] = zp[0]/r,zp[1]/r,zp[2]/r
#xp[0] = 1; xp[1] = 0; xp[2] = 0
#yp[0] = 0; yp[1] = 1; yp[2] = 0
#zp[0] = 0; zp[1] = 0; zp[2] = 1
# random origin or lattice site for new particle
if latflag == 0:
xorig = self.xlo + self.random()*self.xprd
yorig = self.ylo + self.random()*self.yprd
zorig = self.zlo + self.random()*self.zprd
else:
ix = (idmol-1) % self.lattice[0]
iy = (idmol-1)/self.lattice[0] % self.lattice[1]
iz = (idmol-1) / (self.lattice[0]*self.lattice[1])
xorig = self.xlo + ix*self.xprd/self.lattice[0]
yorig = self.ylo + iy*self.yprd/self.lattice[1]
zorig = self.zlo + iz*self.zprd/self.lattice[2]
#xorig = 0; yorig = 0; zorig = 0
# unpack bonds in molecule before atoms so idatom = all previous atoms
for bond in molecule[1]:
idbond += 1
bonds.append([idbond,bond[0],bond[1]+idatom+1,bond[2]+idatom+1])
# unpack triples in molecule as displacements from associated atom
for triple in molecule[2]: triples.append(triple)
# unpack atoms in molecule
# xnew,ynew,xnew = coeffs in new rotated basis vectors
# x,y,z = coeffs in original xyz axes
# format data file for moleular or tri atom style
if self.style == "molecular":
for atom in molecule[0]:
idatom += 1
xnew = atom[1]
ynew = atom[2]
znew = atom[3]
x = xorig + xnew*xp[0] + ynew*yp[0] + znew*zp[0]
y = yorig + xnew*xp[1] + ynew*yp[1] + znew*zp[1]
z = zorig + xnew*xp[2] + ynew*yp[2] + znew*zp[2]
ix = iy = iz = 0
x,y,z,ix,iy,iz = self.pbc(x,y,z,ix,iy,iz)
atoms.append([idatom,idmol,atom[0],x,y,z,ix,iy,iz])
elif self.style == "tri":
for i,atom in enumerate(molecule[0]):
idatom += 1
xnew = atom[1]
ynew = atom[2]
znew = atom[3]
x = xorig + xnew*xp[0] + ynew*yp[0] + znew*zp[0]
y = yorig + xnew*xp[1] + ynew*yp[1] + znew*zp[1]
z = zorig + xnew*xp[2] + ynew*yp[2] + znew*zp[2]
mass = 1.0
ix = iy = iz = 0
x,y,z,ix,iy,iz = self.pbc(x,y,z,ix,iy,iz)
if not triples: triflag = 0
else: triflag = 1
atoms.append([idatom,idmol,atom[0],triflag,mass,x,y,z,ix,iy,iz])
if triflag:
triple = triples[i]
xtri = triple[0]
ytri = triple[1]
ztri = triple[2]
triple[0] = xorig + xtri*xp[0] + ytri*yp[0] + ztri*zp[0]
triple[1] = yorig + xtri*xp[1] + ytri*yp[1] + ztri*zp[1]
triple[2] = zorig + xtri*xp[2] + ytri*yp[2] + ztri*zp[2]
triple[0],triple[1],triple[2] = \
self.pbc_near(triple[0],triple[1],triple[2],x,y,z)
xtri = triple[3]
ytri = triple[4]
ztri = triple[5]
triple[3] = xorig + xtri*xp[0] + ytri*yp[0] + ztri*zp[0]
triple[4] = yorig + xtri*xp[1] + ytri*yp[1] + ztri*zp[1]
triple[5] = zorig + xtri*xp[2] + ytri*yp[2] + ztri*zp[2]
triple[3],triple[4],triple[5] = \
self.pbc_near(triple[3],triple[4],triple[5],x,y,z)
xtri = triple[6]
ytri = triple[7]
ztri = triple[8]
triple[6] = xorig + xtri*xp[0] + ytri*yp[0] + ztri*zp[0]
triple[7] = yorig + xtri*xp[1] + ytri*yp[1] + ztri*zp[1]
triple[8] = zorig + xtri*xp[2] + ytri*yp[2] + ztri*zp[2]
triple[6],triple[7],triple[8] = \
self.pbc_near(triple[6],triple[7],triple[8],x,y,z)
tris.append([idatom] + triple)
# create the data file
list = [atom[2] for atom in atoms]
atypes = max(list)
d = data()
d.title = "LAMMPS data file for Nanoparticles"
d.headers["atoms"] = len(atoms)
d.headers["atom types"] = atypes
if bonds:
d.headers["bonds"] = len(bonds)
d.headers["bond types"] = 1
if tris: d.headers["tris"] = len(tris)
d.headers["xlo xhi"] = (self.xlo,self.xhi)
d.headers["ylo yhi"] = (self.ylo,self.yhi)
d.headers["zlo zhi"] = (self.zlo,self.zhi)
# atoms section of data file
records = []
if self.style == "molecular":
for atom in atoms:
one = "%d %d %d %g %g %g %d %d %d\n" % \
(atom[0], atom[1], atom[2], atom[3], atom[4], atom[5],
atom[6], atom[7], atom[8])
records.append(one)
elif self.style == "tri":
for atom in atoms:
one = "%d %d %d %d %g %g %g %g %d %d %d\n" % \
(atom[0], atom[1], atom[2], atom[3], atom[4], atom[5],
atom[6], atom[7], atom[8], atom[9], atom[10])
records.append(one)
d.sections["Atoms"] = records
# bonds section of data file
if bonds:
lines = []
for bond in bonds:
line = "%d %d %d %d\n" % (bond[0], bond[1], bond[2], bond[3])
lines.append(line)
d.sections["Bonds"] = lines
# triangles section of data file
if tris:
records = []
for tri in tris:
one = "%d %g %g %g %g %g %g %g %g %g\n" % \
(tri[0],tri[1],tri[2],tri[3],tri[4],tri[5],
tri[6],tri[7],tri[8],tri[9])
records.append(one)
d.sections["Triangles"] = records
d.write(file)
# --------------------------------------------------------------------
# write a 2d simulation to data file
def write2d(self,file):
volume = self.volume/self.vfrac
prd = pow(volume/self.xaspect/self.yaspect,1.0/2.0)
self.xprd = self.xaspect * prd
self.xlo = -self.xprd/2.0
self.xhi = self.xprd/2.0
self.yprd = self.yaspect * prd
self.ylo = -self.yprd/2.0
self.yhi = self.yprd/2.0
self.zprd = 1.0
self.zlo = -0.5
self.zhi = 0.5
if self.lattice[0] or self.lattice[1]:
latflag = 1
if self.lattice[0]*self.lattice[1] != len(self.molecules):
raise Exception("lattice inconsistent with # of molecules")
else: latflag = 0
idatom = idbond = idmol = 0
atoms = []
bonds = []
lines = []
xp = 3*[0]
yp = 3*[0]
while self.molecules:
if self.randomized: i = int(self.random()*len(self.molecules))
else: i = 0
molecule = self.molecules.pop(i)
idmol += 1
segments = []
# xp[2],yp[2] = randomly oriented, normalized basis vectors
# xp is in random direction
# yp is (0,0,1) crossed into xp
xp[0] = self.random() - 0.5
xp[1] = self.random() - 0.5
r = sqrt(xp[0]*xp[0] + xp[1]*xp[1])
xp[0],xp[1] = xp[0]/r,xp[1]/r
yp[0] = -xp[1]
yp[1] = xp[0]
r = sqrt(yp[0]*yp[0] + yp[1]*yp[1])
yp[0],yp[1] = yp[0]/r,yp[1]/r
# random origin or lattice site for new particle
if latflag == 0:
xorig = self.xlo + self.random()*self.xprd
yorig = self.ylo + self.random()*self.yprd
zorig = 0.0
else:
ix = (idmol-1) % self.lattice[0]
iy = (idmol-1) / self.lattice[0]
xorig = self.xlo + ix*self.xprd/self.lattice[0]
yorig = self.ylo + iy*self.yprd/self.lattice[1]
zorig = 0.0
# unpack bonds in molecule before atoms so idatom = all previous atoms
for bond in molecule[1]:
idbond += 1
bonds.append([idbond,bond[0],bond[1]+idatom+1,bond[2]+idatom+1])
# unpack segments in molecule as displacements from associated atom
for segment in molecule[3]: segments.append(segment)
# unpack atoms in molecule
# xnew,ynew,xnew = coeffs in new rotated basis vectors
# x,y,z = coeffs in original xyz axes
# format data file for moleular or line atom style
if self.style == "molecular":
for i,atom in enumerate(molecule[0]):
idatom += 1
xnew = atom[1]
ynew = atom[2]
x = xorig + xnew*xp[0] + ynew*yp[0]
y = yorig + xnew*xp[1] + ynew*yp[1]
z = atom[3]
ix = iy = iz = 0
x,y,z,ix,iy,iz = self.pbc(x,y,z,ix,iy,iz)
atoms.append([idatom,idmol,atom[0],x,y,z,ix,iy,iz])
elif self.style == "line":
for i,atom in enumerate(molecule[0]):
idatom += 1
xnew = atom[1]
ynew = atom[2]
x = xorig + xnew*xp[0] + ynew*yp[0]
y = yorig + xnew*xp[1] + ynew*yp[1]
z = atom[3]
mass = 1.0
ix = iy = iz = 0
x,y,z,ix,iy,iz = self.pbc(x,y,z,ix,iy,iz)
if not segments: lineflag = 0
else: lineflag = 1
atoms.append([idatom,idmol,atom[0],lineflag,mass,x,y,z,ix,iy,iz])
if lineflag:
segment = segments[i]
xseg = xnew + segment[0]
yseg = ynew + segment[1]
segment[0] = xorig + xseg*xp[0] + yseg*yp[0]
segment[1] = yorig + xseg*xp[1] + yseg*yp[1]
segment[0],segment[1],tmp = \
self.pbc_near(segment[0],segment[1],0,x,y,z)
xseg = xnew + segment[2]
yseg = ynew + segment[3]
segment[2] = xorig + xseg*xp[0] + yseg*yp[0]
segment[3] = yorig + xseg*xp[1] + yseg*yp[1]
segment[2],segment[3],tmp = \
self.pbc_near(segment[2],segment[3],0,x,y,z)
lines.append([idatom] + segment)
# create the data file
list = [atom[2] for atom in atoms]
atypes = max(list)
d = data()
d.title = "LAMMPS data file for Nanoparticles"
d.headers["atoms"] = len(atoms)
d.headers["atom types"] = atypes
if bonds:
d.headers["bonds"] = len(bonds)
d.headers["bond types"] = 1
if lines: d.headers["lines"] = len(lines)
d.headers["xlo xhi"] = (self.xlo,self.xhi)
d.headers["ylo yhi"] = (self.ylo,self.yhi)
d.headers["zlo zhi"] = (self.zlo,self.zhi)
# atoms section of data file
records = []
if self.style == "molecular":
for atom in atoms:
one = "%d %d %d %g %g %g %d %d %d\n" % \
(atom[0], atom[1], atom[2], atom[3], atom[4], atom[5],
atom[6], atom[7], atom[8])
records.append(one)
elif self.style == "line":
for atom in atoms:
one = "%d %d %d %d %g %g %g %g %d %d %d\n" % \
(atom[0], atom[1], atom[2], atom[3], atom[4], atom[5],
atom[6], atom[7], atom[8], atom[9], atom[10])
records.append(one)
d.sections["Atoms"] = records
# bonds section of data file
if bonds:
records = []
for bond in bonds:
one = "%d %d %d %d\n" % (bond[0], bond[1], bond[2], bond[3])
records.append(one)
d.sections["Bonds"] = records
# lines section of data file
if lines:
records = []
for line in lines:
one = "%d %g %g %g %g\n" % (line[0],line[1],line[2],line[3],line[4])
records.append(one)
d.sections["Lines"] = records
d.write(file)
# --------------------------------------------------------------------
# adjust x,y,z to be inside periodic box
def pbc(self,x,y,z,ix,iy,iz):
if x < self.xlo:
x += self.xprd
ix -= 1
elif x >= self.xhi:
x -= self.xprd
ix += 1
if y < self.ylo:
y += self.yprd
iy -= 1
elif y >= self.yhi:
y -= self.yprd
iy += 1
if z < self.zlo:
z += self.zprd
iz -= 1
elif z >= self.zhi:
z -= self.zprd
iz += 1
return x,y,z,ix,iy,iz
# --------------------------------------------------------------------
# adjust xnew,ynew,znew to be near x,y,z in periodic sense
def pbc_near(self,xnew,ynew,znew,x,y,z):
if x-xnew > 0.5*self.xprd: xnew += self.xprd
elif xnew-x > 0.5*self.xprd: xnew -= self.xprd
if y-ynew > 0.5*self.yprd: ynew += self.yprd
elif ynew-y > 0.5*self.yprd: ynew -= self.yprd
if z-znew > 0.5*self.zprd: znew += self.zprd
elif znew-z > 0.5*self.zprd: znew -= self.zprd
return xnew,ynew,znew
# --------------------------------------------------------------------
# params = diam,type1,type2,type3
# type1 = type of non-patch atoms, type2 = type of patch atoms
# type3 = type of center-of-sphere atom
def c60hex2(self,*params):
template = BUCKY_60
diam = params[0]
patches = [[params[2],[1,2,3,4,5,6,34,35,46,47,48,60]],
[params[3],[61]]]
atoms = make_sphere(template,diam,params[1],patches)
volume = 4.0/3.0 * pi * diam*diam*diam/8
return atoms,[],[],[],volume
# --------------------------------------------------------------------
# params = diam,type1,type2
# type1 = type of large center atom, type2 = type of hex patch atoms
def hex2(self,*params):
diam = params[0]
type1 = params[1]
type2 = params[2]
atoms = []
atoms.append([type1,0.0,0.0,0.0])
atoms.append(atom_on_sphere(diam,type2,0.5*diam,0.0,0.0))
atoms.append(atom_on_sphere(diam,type2,0.5*diam,1.0,0.0))
atoms.append(atom_on_sphere(diam,type2,0.5*diam,-1.0,0.0))
atoms.append(atom_on_sphere(diam,type2,0.5*diam,0.5,sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,0.5*diam,-0.5,sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,0.5*diam,0.5,-sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,0.5*diam,-0.5,-sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,-0.5*diam,0.0,0.0))
atoms.append(atom_on_sphere(diam,type2,-0.5*diam,1.0,0.0))
atoms.append(atom_on_sphere(diam,type2,-0.5*diam,-1.0,0.0))
atoms.append(atom_on_sphere(diam,type2,-0.5*diam,0.5,sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,-0.5*diam,-0.5,sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,-0.5*diam,0.5,-sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,-0.5*diam,-0.5,-sqrt(3.0)/2))
volume = 4.0/3.0 * pi * diam*diam*diam/8
return atoms,[],[],[],volume
# --------------------------------------------------------------------
# params = diam,type1,type2
# type1 = type of large center atom, type2 = type of hex patch atoms
def hex4(self,*params):
diam = params[0]
type1 = params[1]
type2 = params[2]
atoms = []
atoms.append([type1,0.0,0.0,0.0])
atoms.append(atom_on_sphere(diam,type2,0.5*diam,0.0,0.0))
atoms.append(atom_on_sphere(diam,type2,0.5*diam,1.0,0.0))
atoms.append(atom_on_sphere(diam,type2,0.5*diam,-1.0,0.0))
atoms.append(atom_on_sphere(diam,type2,0.5*diam,0.5,sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,0.5*diam,-0.5,sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,0.5*diam,0.5,-sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,0.5*diam,-0.5,-sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,-0.5*diam,0.0,0.0))
atoms.append(atom_on_sphere(diam,type2,-0.5*diam,1.0,0.0))
atoms.append(atom_on_sphere(diam,type2,-0.5*diam,-1.0,0.0))
atoms.append(atom_on_sphere(diam,type2,-0.5*diam,0.5,sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,-0.5*diam,-0.5,sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,-0.5*diam,0.5,-sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,-0.5*diam,-0.5,-sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,0.0,0.5*diam,0.0))
atoms.append(atom_on_sphere(diam,type2,1.0,0.5*diam,0.0))
atoms.append(atom_on_sphere(diam,type2,-1.0,0.5*diam,0.0))
atoms.append(atom_on_sphere(diam,type2,0.5,0.5*diam,sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,-0.5,0.5*diam,sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,0.5,0.5*diam,-sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,-0.5,0.5*diam,-sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,0.0,-0.5*diam,0.0))
atoms.append(atom_on_sphere(diam,type2,1.0,-0.5*diam,0.0))
atoms.append(atom_on_sphere(diam,type2,-1.0,-0.5*diam,0.0))
atoms.append(atom_on_sphere(diam,type2,0.5,-0.5*diam,sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,-0.5,-0.5*diam,sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,0.5,-0.5*diam,-sqrt(3.0)/2))
atoms.append(atom_on_sphere(diam,type2,-0.5,-0.5*diam,-sqrt(3.0)/2))
volume = 4.0/3.0 * pi * diam*diam*diam/8
return atoms,[],[],[],volume
# --------------------------------------------------------------------
# params = diam,nring,type1,type2
# nring = # of particles in ring
# type1 = type of large center atom, type2 = type of ring atoms
def ring(self,*params):
diam = params[0]
nring = params[1]
type1 = params[2]
type2 = params[3]
atoms = []
atoms.append([type1,0.0,0.0,0.0])
for i in range(nring):
atoms.append([type2,0.5*diam*cos(i * 2*pi/nring),
0.5*diam*sin(i * 2*pi/nring),0.0])
volume = 4.0/3.0 * pi * diam*diam*diam/8
return atoms,[],[],[],volume
# --------------------------------------------------------------------
# params = diam,m1,m2,ntype,m1type,m2type
# ntype = type of big central ball
# m12,m12type = length of tethers on each side of ball (m12 = 0 = no tether)
# set three types of bonds:
# 1 = big to small, 2 = small to small, 3 = across two tethers
def ball(self,*params):
diam = params[0]
m1 = params[1]
m2 = params[2]
ntype = params[3]
m1type = params[4]
m2type = params[5]
atoms = []
atoms.append([ntype,0.0,0.0,0.0])
if m1:
atoms.append([m1type,0.5*diam+0.5,0.0,0.0])
atoms += tether(m1-1,m1type,self.blen,self.dmin,
[ntype,0.5*diam-0.5,0.0,0.0],atoms[1],self.random)
if m2:
atoms.append([m2type,-0.5*diam-0.5,0.0,0.0])
atoms += tether(m2-1,m2type,self.blen,self.dmin,
[ntype,-0.5*diam+0.5,0.0,0.0],atoms[1+m1],self.random)
bonds = []
for i in range(m1):
if i == 0: bonds.append([1,0,1])
else: bonds.append([2,1+i-1,1+i])
for i in range(m2):
if i == 0: bonds.append([1,0,1+m1])
else: bonds.append([2,1+m1+i-1,1+m1+i])
if m1 and m2: bonds.append([3,1,m1+1])
volume = 4.0/3.0 * pi * diam*diam*diam/8 + (m1+m2)*pi/6.0
return atoms,bonds,[],[],volume
# --------------------------------------------------------------------
# params = type1,type2
# type1 = type of 1/3 layers, type2 = type of middle layer
def tri5(self,*params):
template = TRI5_HOLLOW
nlayer = 3
patches = [[params[1],[13,14,15,16,17,18,19,20,21,22,23,24]]]
atoms = []
n = 0
for iz in range(nlayer):
for atom in template:
n += 1
type = params[0]
for pair in patches:
patch = pair[1]
if n in patch: type = pair[0]
x,y,z = atom[0],atom[1],atom[2] + iz
atoms.append([type,x,y,z])
volume = nlayer * 0.5 * 5.0 * 5.0*sqrt(3)/2
return atoms,[],[],[],volume
# --------------------------------------------------------------------
# params = n,m1,m2,ntype,m1type,m2type
# n,ntype = length/type of rod
# m12,m12type = length of tethers on each end (m12 = 0 = no tether)
def rod(self,*params):
n = params[0]
m1 = params[1]
m2 = params[2]
ntype = params[3]
m1type = params[4]
m2type = params[5]
atoms = []
for i in range(n):
x,y,z = i*self.blen,0.0,0.0
atoms.append([ntype,x,y,z])
if m1: atoms += tether(m1,m1type,self.blen,self.dmin,
atoms[n-2],atoms[n-1],self.random)
if m2: atoms += tether(m2,m2type,self.blen,self.dmin,
atoms[1],atoms[0],self.random)
bonds = []
for i in range(m1):
if i == 0: bonds.append([1,n-1,n])
else: bonds.append([1,n+i-1,n+i])
for i in range(m2):
if i == 0: bonds.append([1,0,n+m1])
else: bonds.append([1,n+m1+i-1,n+m1+i])
volume = (n+m1+m2) * pi / 6.0
return atoms,bonds,[],[],volume
# --------------------------------------------------------------------
# params = nsize,m1,m2,m3,ntype,m1type,m2type,m3type
# nsize,ntype = size,type of triangle center
# m123,m123type = length of tethers on each corner (m123 = 0 = no tether)
def tri(self,*params):
nsize = params[0]
m1 = params[1]
m2 = params[2]
m3 = params[3]
ntype = params[4]
m1type = params[5]
m2type = params[6]
m3type = params[7]
atoms = []
for i in range(nsize):
n = nsize - i
for j in range(n):
x,y,z = 0.5*i*self.blen + j*self.blen, i*self.blen*sqrt(3.0)/2.0, 0.0
atoms.append([ntype,x,y,z])
n = len(atoms)
if m1: atoms += tether(m1,m1type,self.blen,self.dmin,
atoms[1],atoms[0],self.random)
if m2: atoms += tether(m2,m2type,self.blen,self.dmin,
atoms[nsize-2],atoms[nsize-1],self.random)
if m3: atoms += tether(m3,m3type,self.blen,self.dmin,
atoms[n-2],atoms[n-1],self.random)
bonds = []
for i in range(m1):
if i == 0: bonds.append([1,0,n])
else: bonds.append([1,n+i-1,n+i])
for i in range(m2):
if i == 0: bonds.append([1,nsize-1,n+m1])
else: bonds.append([1,n+m1+i-1,n+m1+i])
for i in range(m3):
if i == 0: bonds.append([1,n-1,n+m1+m2])
else: bonds.append([1,n+m1+m2+i-1,n+m1+m2+i])
volume = (nsize*(nsize+1)/2 + m1+m2+m3) * pi / 6.0
return atoms,bonds,[],[],volume
# --------------------------------------------------------------------
# params = m1,m2,m3,m4,m5,m6,ntype,m1type,m2type,m3type,m4type,m5type,m6type
# ntype = type of hex center
# m123456,m123456type = length of tethers on each corner (m = 0 = no tether)
def hex(self,*params):
m1 = params[0]
m2 = params[1]
m3 = params[2]
m4 = params[3]
m5 = params[4]
m6 = params[5]
ntype = params[6]
m1type = params[7]
m2type = params[8]
m3type = params[9]
m4type = params[10]
m5type = params[11]
m6type = params[12]
atoms = []
atoms.append([ntype,0.0,0.0,0.0])
atoms.append([ntype,self.blen,0.0,0.0])
atoms.append([ntype,-self.blen,0.0,0.0])
atoms.append([ntype,self.blen/2.0,self.blen*sqrt(3.0)/2.0,0.0])
atoms.append([ntype,-self.blen/2.0,self.blen*sqrt(3.0)/2.0,0.0])
atoms.append([ntype,self.blen/2.0,-self.blen*sqrt(3.0)/2.0,0.0])
atoms.append([ntype,-self.blen/2.0,-self.blen*sqrt(3.0)/2.0,0.0])
n = len(atoms)
if m1: atoms += tether(m1,m1type,self.blen,self.dmin,
atoms[0],atoms[1],self.random)
if m2: atoms += tether(m2,m2type,self.blen,self.dmin,
atoms[0],atoms[2],self.random)
if m3: atoms += tether(m3,m3type,self.blen,self.dmin,
atoms[0],atoms[3],self.random)
if m4: atoms += tether(m4,m4type,self.blen,self.dmin,
atoms[0],atoms[4],self.random)
if m5: atoms += tether(m5,m5type,self.blen,self.dmin,
atoms[0],atoms[5],self.random)
if m6: atoms += tether(m6,m6type,self.blen,self.dmin,
atoms[0],atoms[6],self.random)
bonds = []
for i in range(m1):
if i == 0: bonds.append([1,1,n])
else: bonds.append([1,n+i-1,n+i])
for i in range(m2):
if i == 0: bonds.append([1,2,n+m1])
else: bonds.append([1,n+m1+i-1,n+m1+i])
for i in range(m3):
if i == 0: bonds.append([1,3,n+m1+m2])
else: bonds.append([1,n+m1+m2+i-1,n+m1+m2+i])
for i in range(m4):
if i == 0: bonds.append([1,4,n+m1+m2+m3])
else: bonds.append([1,n+m1+m2+m3+i-1,n+m1+m2+m3+i])
for i in range(m5):
if i == 0: bonds.append([1,5,n+m1+m2+m3+m4])
else: bonds.append([1,n+m1+m2+m3+m4+i-1,n+m1+m2+m3+m4+i])
for i in range(m6):
if i == 0: bonds.append([1,6,n+m1+m2+m3+m4+m5])
else: bonds.append([1,n+m1+m2+m3+m4+m5+i-1,n+m1+m2+m3+m4+m5+i])
volume = (7 + m1+m2+m3+m4+m5+m6) * pi / 6.0
return atoms,bonds,[],[],volume
# --------------------------------------------------------------------
# params = sep,type
# sep = separation distance of two particles
# type = type of 2 particles
def dimer(self,*params):
sep = params[0]
type = params[1]
atoms = []
x,y,z = 0.0,0.0,0.0
atoms.append([type,x,y,z])
x,y,z = sep,0.0,0.0
atoms.append([type,x,y,z])
volume = 2 * pi / 6.0 # need to account for overlap and 2d/3d
return atoms,[],[],[],volume
# --------------------------------------------------------------------
# params = N,sep,type
# N = lengths of each arm of star (must be odd)
# sep = separation distance of consecutive particles
# type = type of all particles
def star2d(self,*params):
n = params[0]
sep = params[1]
type = params[2]
if n % 2 == 0:
raise Exception("N in patch::star2d is not odd")
middle = n/2
atoms = []
x,y,z = 0.0,0.0,0.0
atoms.append([type,x,y,z])
for i in range(n):
i -= middle
if i == 0: continue
x,y,z = i*sep,0.0,0.0
atoms.append([type,x,y,z])
for i in range(n):
i -= middle
if i == 0: continue
x,y,z = 0.0,i*sep,0.0
atoms.append([type,x,y,z])
volume = (2*n-1) * pi / 6.0 # need to account for overlap and 2d/3d
return atoms,[],[],[],volume
# --------------------------------------------------------------------
# params = N,M,sep,type
# N,M = lengths of each side of box
# sep = separation distance of consecutive particles
# type = type of all particles
def box2d(self,*params):
n = params[0]
m = params[1]
sep = params[2]
type = params[3]
height = (m-1) * sep
width = (n-1) * sep
atoms = []
for i in range(n):
x,y,z = i*sep,0.0,0.0
atoms.append([type,x,y,z])
for i in range(n):
x,y,z = i*sep,height,0.0
atoms.append([type,x,y,z])
for i in range(1,m-1,1):
x,y,z = 0.0,i*sep,0.0
atoms.append([type,x,y,z])
for i in range(1,m-1,1):
x,y,z = width,i*sep,0.0
atoms.append([type,x,y,z])
volume = (2*(n+m-2)) * pi / 6.0 # need to account for overlap and 2d/3d
return atoms,[],[],[],volume
# --------------------------------------------------------------------
# params = a,type
# a = edge length of tet
# type = type of each vertex in tet
def tritet(self,*params):
a = params[0]
type = params[1]
cubeside = a/sqrt(2)
v = 0.5*cubeside
atoms = []
tris = []
# 4 corner pts of tet
c1 = [+v/2,+v/2,+v/2]
c2 = [-v/2,-v/2,+v/2]
c3 = [-v/2,+v/2,-v/2]
c4 = [+v/2,-v/2,-v/2]
# 4 triangles on faces of tet, outward normals via rh rule
tris.append(c1+c3+c2)
tris.append(c1+c2+c4)
tris.append(c1+c3+c4)
tris.append(c2+c3+c4)
# 4 atoms at centroids of 4 triangles
atoms.append([type,(c1[0]+c3[0]+c2[0])/3.0,(c1[1]+c3[1]+c2[1])/3.0,
(c1[2]+c3[2]+c2[2])/3.0])
atoms.append([type,(c1[0]+c2[0]+c4[0])/3.0,(c1[1]+c2[1]+c4[1])/3.0,
(c1[2]+c2[2]+c4[2])/3.0])
atoms.append([type,(c1[0]+c3[0]+c4[0])/3.0,(c1[1]+c3[1]+c4[1])/3.0,
(c1[2]+c3[2]+c4[2])/3.0])
atoms.append([type,(c2[0]+c3[0]+c4[0])/3.0,(c2[1]+c3[1]+c4[1])/3.0,
(c2[2]+c3[2]+c4[2])/3.0])
volume = sqrt(2)/12 * a*a*a
return atoms,[],tris,[],volume
# --------------------------------------------------------------------
# params = Alo,Ahi,Blo,Bhi,Clo,Chi,type
# Alo to Ahi = bounds of edge length in x of box
# Blo to Bhi = bounds of edge length in y of box
# Clo to Chi = bounds of edge length in y of box
# type = type of each vertex in rectangular box
def tribox(self,*params):
alo = params[0]
ahi = params[1]
blo = params[2]
bhi = params[3]
clo = params[4]
chi = params[5]
type = params[6]
a = alo + self.random()*(ahi-alo)
b = blo + self.random()*(bhi-blo)
c = clo + self.random()*(chi-clo)
atoms = []
tris = []
# 8 corner pts of rectangular box
c1 = [-a/2,-b/2,-c/2]
c2 = [+a/2,-b/2,-c/2]
c3 = [-a/2,+b/2,-c/2]
c4 = [+a/2,+b/2,-c/2]
c5 = [-a/2,-b/2,+c/2]
c6 = [+a/2,-b/2,+c/2]
c7 = [-a/2,+b/2,+c/2]
c8 = [+a/2,+b/2,+c/2]
# 12 triangles on faces of cube, outward normals via rh rule
tris.append(c1+c7+c3)
tris.append(c1+c5+c7)
tris.append(c2+c4+c8)
tris.append(c2+c8+c6)
tris.append(c1+c2+c6)
tris.append(c1+c6+c5)
tris.append(c3+c8+c4)
tris.append(c3+c7+c8)
tris.append(c1+c4+c2)
tris.append(c1+c3+c4)
tris.append(c5+c6+c8)
tris.append(c5+c8+c7)
# 12 atoms at centroids of 12 triangles
atoms.append([type,(c1[0]+c7[0]+c3[0])/3.0,(c1[1]+c7[1]+c3[1])/3.0,
(c1[2]+c7[2]+c3[2])/3.0])
atoms.append([type,(c1[0]+c5[0]+c7[0])/3.0,(c1[1]+c5[1]+c7[1])/3.0,
(c1[2]+c5[2]+c7[2])/3.0])
atoms.append([type,(c2[0]+c4[0]+c8[0])/3.0,(c2[1]+c4[1]+c8[1])/3.0,
(c2[2]+c4[2]+c8[2])/3.0])
atoms.append([type,(c2[0]+c8[0]+c6[0])/3.0,(c2[1]+c8[1]+c6[1])/3.0,
(c2[2]+c8[2]+c6[2])/3.0])
atoms.append([type,(c1[0]+c2[0]+c6[0])/3.0,(c1[1]+c2[1]+c6[1])/3.0,
(c1[2]+c2[2]+c6[2])/3.0])
atoms.append([type,(c1[0]+c6[0]+c5[0])/3.0,(c1[1]+c6[1]+c5[1])/3.0,
(c1[2]+c6[2]+c5[2])/3.0])
atoms.append([type,(c3[0]+c8[0]+c4[0])/3.0,(c3[1]+c8[1]+c4[1])/3.0,
(c3[2]+c8[2]+c4[2])/3.0])
atoms.append([type,(c3[0]+c7[0]+c8[0])/3.0,(c3[1]+c7[1]+c8[1])/3.0,
(c3[2]+c7[2]+c8[2])/3.0])
atoms.append([type,(c1[0]+c4[0]+c2[0])/3.0,(c1[1]+c4[1]+c2[1])/3.0,
(c1[2]+c4[2]+c2[2])/3.0])
atoms.append([type,(c1[0]+c3[0]+c4[0])/3.0,(c1[1]+c3[1]+c4[1])/3.0,
(c1[2]+c3[2]+c4[2])/3.0])
atoms.append([type,(c5[0]+c6[0]+c8[0])/3.0,(c5[1]+c6[1]+c8[1])/3.0,
(c5[2]+c6[2]+c8[2])/3.0])
atoms.append([type,(c5[0]+c8[0]+c7[0])/3.0,(c5[1]+c8[1]+c7[1])/3.0,
(c5[2]+c8[2]+c7[2])/3.0])
volume = a*b*c
return atoms,[],tris,[],volume
# --------------------------------------------------------------------
# params = Alo,Ahi,Blo,Bhi,type
# Alo to Ahi = bounds of edge length in x of rectangle
# Blo to Bhi = bounds of edge length in y of rectangle
# type = type of each line segment in rectangle
def linebox(self,*params):
alo = float(params[0])
ahi = float(params[1])
blo = float(params[2])
bhi = float(params[3])
type = params[4]
a = alo + self.random()*(ahi-alo)
b = blo + self.random()*(bhi-blo)
atoms = []
segments = []
# 4 atoms at center points of line segments in 2d
atoms.append([type,0,-b/2,0])
atoms.append([type,a/2,0,0])
atoms.append([type,0,b/2,0])
atoms.append([type,-a/2,0,0])
# 4 line segments as displacements from atom
segments.append([-a/2,0,a/2,0])
segments.append([0,-b/2,0,b/2])
segments.append([a/2,0,-a/2,0])
segments.append([0,b/2,0,-b/2])
volume = a*b
return atoms,[],[],segments,volume
# --------------------------------------------------------------------
# params = Alo,Ahi,Blo,Bhi,type
# Alo to Ahi = bounds of base length in x of triangle
# Blo to Bhi = bounds of heigth in y of isosceles triangle
# type = type of each line segment in triangle
def linetri(self,*params):
alo = float(params[0])
ahi = float(params[1])
blo = float(params[2])
bhi = float(params[3])
type = params[4]
base = alo + self.random()*(ahi-alo)
ht = blo + self.random()*(bhi-blo)
atoms = []
segments = []
# 3 atoms at center points of line segments in 2d
atoms.append([type,0,-ht/2,0])
atoms.append([type,base/4,0,0])
atoms.append([type,-base/4,0,0])
# 3 line segments as displacements from atom
segments.append([-base/2,0,base/2,0])
segments.append([base/4,-ht/2,-base/4,ht/2])
segments.append([base/4,ht/2,-base/4,-ht/2])
volume = 0.5*base*ht
return atoms,[],[],segments,volume
# --------------------------------------------------------------------
def random(self):
k = self.seed//IQ
self.seed = IA*(self.seed-k*IQ) - IR*k
if self.seed < 0:
self.seed += IM
return AM*self.seed
# --------------------------------------------------------------------
# random number generator class
IM = 2147483647
AM = 1.0/IM
IA = 16807
IQ = 127773
IR = 2836
# --------------------------------------------------------------------
# push atom onto sphere surface of diam and return [type,x,y,z]
def atom_on_sphere(diam,type,x,y,z):
if x == 0.0 and y == 0.0 and z == 0.0: scale = 0.0
else: scale = 0.5*diam / sqrt(x*x + y*y + z*z)
return [type,scale*x,scale*y,scale*z]
# --------------------------------------------------------------------
# make a sphere from a template with some atoms in patches w/ different types
def make_sphere(template,diam,type0,patches):
atoms = []
n = 0
for atom in template:
n += 1
type = type0
for pair in patches:
patch = pair[1]
if n in patch:
type = pair[0]
atoms.append(atom_on_sphere(diam,type,atom[0],atom[1],atom[2]))
return atoms
# --------------------------------------------------------------------
# build a tether of length M of mtype, connected to atom1 with prev atom0
# blen = bond length between successive tether atoms
# dmin = length restriction between atoms i-1,i+1
def tether(m,mtype,blen,dmin,atom0,atom1,random):
atoms = [atom0,atom1]
for i in range(m):
imonomer = len(atoms)
restriction = True
while restriction:
rsq = 2.0
while rsq > 1.0:
dx = 2.0*random() - 1.0
dy = 2.0*random() - 1.0
dz = 2.0*random() - 1.0
rsq = dx*dx + dy*dy + dz*dz
r = sqrt(rsq)
dx,dy,dz = dx/r,dy/r,dz/r
x = atoms[imonomer-1][1] + dx*blen
y = atoms[imonomer-1][2] + dy*blen
z = atoms[imonomer-1][3] + dz*blen
dx = x - atoms[imonomer-2][1]
dy = y - atoms[imonomer-2][2]
dz = z - atoms[imonomer-2][3]
restriction = False
if sqrt(dx*dx + dy*dy + dz*dz) <= dmin: restriction = True
if not restriction: atoms.append([mtype,x,y,z])
return atoms[2:]
# --------------------------------------------------------------------
# templates
TRI5_HOLLOW = ((0,0,0),(1,0,0),(2,0,0),(3,0,0),(4,0,0),
(0.5,sqrt(3)/2,0),(3.5,sqrt(3)/2,0),
(1.0,2*sqrt(3)/2,0),(3.0,2*sqrt(3)/2,0),
(1.5,3*sqrt(3)/2,0),(2.5,3*sqrt(3)/2,0),
(2.0,4*sqrt(3)/2,0))
SIMPLE_7 = ((0,0,0),(1,0,0),(-1,0,0),(0,1,0),(0,-1,0),(0,0,1),(0,0,-1))
# C60 with added center point at end
BUCKY_60 = ((0.014416695, 1.232517, -3.260650),
(1.236417, 1.719517, -2.768650),
(2.292417, 0.8265171, -2.492650),
(2.122416, -0.5504832, -2.709650),
(0.8954167, -1.040483, -3.204650),
(-0.1565833, -0.1504831, -3.479650),
(-1.018583, 1.984517, -2.678650),
(-0.4355836, 2.936517, -1.826650),
(0.9584165, 2.773517, -1.881650),
(1.734416, 2.937517, -0.7156501),
(3.065417, 0.9905167, -1.331650),
(2.790417, -1.238483, -1.682650),
(2.234416, -2.418483, -1.146650),
(1.012417, -2.905483, -1.638650),
(0.3414168, -2.215483, -2.669650),
(-1.052583, -2.051483, -2.614650),
(-1.360583, -0.7754831, -3.114650),
(-2.397583, -0.020483017, -2.529650),
(-2.227583, 1.356517, -2.312650),
(-1.059583, 3.265517, -0.6046500),
(-2.262583, 2.640517, -0.2406499),
(-2.848583, 1.684517, -1.095650),
(-3.402583, 0.5095167, -0.5616500),
(-3.124583, -0.5444832, -1.447650),
(-2.815583, -1.825483, -0.9456501),
(-1.781583, -2.577483, -1.527650),
(-1.113584, -3.265483, -0.5006499),
(0.2864165, -3.429483, -0.5566499),
(3.373417, -0.2854834, -0.8306501),
(1.018416, -1.984483, 2.678350),
(2.227417, -1.356483, 2.312350),
(2.398417, 0.020516872, 2.530350),
(1.360417, 0.7755170, 3.114350),
(0.1564164, 0.1505170, 3.479350),
(-1.236583, -1.719483, 2.768350),
(-0.9585834, -2.773483, 1.882350),
(0.4354167, -2.936483, 1.826350),
(1.059417, -3.265483, 0.6053500),
(2.263417, -2.640483, 0.2403500),
(2.848417, -1.684483, 1.096350),
(3.124417, 0.5445170, 1.447350),
(2.815417, 1.825517, 0.9453500),
(1.781417, 2.577517, 1.527350),
(1.052417, 2.051517, 2.614350),
(-0.3415833, 2.215517, 2.669350),
(-0.8955836, 1.040517, 3.204350),
(-2.122583, 0.5505171, 2.710350),
(-2.292583, -0.8264832, 2.492350),
(-1.734583, -2.937483, 0.7163500),
(-2.786583, -2.048483, 0.4413500),
(-3.065583, -0.9904833, 1.331350),
(-3.373584, 0.2855167, 0.8313500),
(-2.790584, 1.238517, 1.683350),
(-2.233583, 2.418517, 1.146350),
(-1.011583, 2.905517, 1.638350),
(-0.2855835, 3.429517, 0.5563500),
(1.113417, 3.265517, 0.5003500),
(3.402417, -0.5094833, 0.5613500),
(2.786417, 2.047517, -0.4416499),
(-0.014583588, -1.232483, 3.261350),
(0.0, 0.0, 0.0))
# --------------------------------------------------------------------
# C80
BUCKY_80 = ((-1.243762, -0.7016125, 3.734700),
(-1.248762, 0.6973875, 3.749700),
(-0.054762483, 1.429388, 3.749700),
(1.189238, 0.7893875, 3.735700),
(1.194237, -0.6086125, 3.783700),
(0.00023752451, -1.340613, 3.782700),
(-2.204762, 1.428387, 3.034700),
(-3.191762, 0.7883875, 2.276700),
(-3.223763, -0.6096125, 2.311700),
(-2.267762, -1.340613, 3.027700),
(0.2282375, -2.540613, 3.098700),
(-0.7787625, -3.147613, 2.340700),
(-2.039762, -2.541613, 2.343700),
(2.160238, -1.356613, 3.098700),
(1.563237, -2.550612, 2.675700),
(-0.2727625, 2.612388, 3.034700),
(-1.601763, 2.612388, 2.591700),
(-3.586762, -1.357612, 1.184700),
(-2.854763, -2.551612, 1.204700),
(2.223238, 1.412387, 3.028700),
(2.006238, 2.595387, 2.312700),
(0.7452375, 3.202387, 2.276700),
(0.3742375, 3.844388, 1.090700),
(-0.9547625, 3.844388, 0.6487002),
(-1.962763, 3.201387, 1.374700),
(-2.992763, 2.595387, 0.6477003),
(-3.595763, 1.411387, 1.090700),
(-3.958763, 0.6633875, -0.036299706),
(-3.930763, -0.7356125, -0.020299911),
(-3.568762, -1.385612, -1.205300),
(-2.837763, -2.579613, -1.186300),
(-2.439763, -3.168612, 0.019700050),
(-1.205762, -3.828612, 0.035700321),
(-0.3907624, -3.817612, 1.174700),
(0.9442375, -3.827612, 0.7516999),
(1.941237, -3.168612, 1.478700),
(3.190238, 0.6643875, 2.343700),
(3.158237, -0.7346125, 2.340700),
(3.579237, -1.384613, 1.175700),
(2.982238, -2.578612, 0.7527003),
(1.244238, 0.7023875, -3.735300),
(1.249238, -0.6976125, -3.750300),
(0.055237532, -1.428612, -3.750300),
(-1.189762, -0.7896125, -3.735300),
(-1.193763, 0.6093875, -3.783300),
(0.00023752451, 1.340387, -3.783300),
(2.205238, -1.428612, -3.034300),
(3.192237, -0.7886125, -2.276300),
(3.224237, 0.6093875, -2.312300),
(2.268238, 1.341388, -3.027300),
(-0.2277625, 2.541388, -3.098300),
(0.7792375, 3.147388, -2.340300),
(2.040237, 2.541388, -2.343300),
(-2.159763, 1.356387, -3.098300),
(-1.562762, 2.550387, -2.675300),
(0.2732375, -2.612613, -3.034300),
(1.601238, -2.612613, -2.592300),
(3.586237, 1.357388, -1.185300),
(2.854238, 2.551387, -1.204300),
(-2.223763, -1.411613, -3.028300),
(-2.005763, -2.595613, -2.312300),
(-0.7457625, -3.201612, -2.277300),
(-0.3747625, -3.844613, -1.090300),
(0.9542375, -3.844613, -0.6482999),
(1.962238, -3.201612, -1.375300),
(2.992238, -2.595613, -0.6482999),
(3.596237, -1.411613, -1.090300),
(3.958237, -0.6636125, 0.036700249),
(3.931237, 0.7353874, 0.019700050),
(3.569237, 1.385387, 1.205700),
(2.837237, 2.579388, 1.185700),
(2.439238, 3.168387, -0.019299984),
(1.205238, 3.828387, -0.036299706),
(0.3902375, 3.818388, -1.175300),
(-0.9447625, 3.828387, -0.7522998),
(-1.941762, 3.168387, -1.478300),
(-3.189763, -0.6646125, -2.344300),
(-3.157763, 0.7343875, -2.340300),
(-3.579762, 1.384387, -1.175300),
(-2.982763, 2.578387, -0.7522998))