lammps/tools/polybond/lmpsdata.py

1946 lines
82 KiB
Python
Raw Normal View History

#
#
# lmpsdata.py
#
# For reading, writing and manipulating lammps data files
# For calculation of certain properities using lammps data files
# For creating VMD input text files using lammps data files
# All x,y,z calculations assume the information includes image flags
class Lmpsdata:
def __init__(self,file,atomtype):
"""initiates lammps data structures"""
self.atomtype=atomtype
self.keywords=[]
self.atoms=[]
self.angles=[]
self.bonds=[]
self.dihedrals=[]
self.dipoles=[]
self.impropers=[]
self.masses=[]
self.shapes=[]
self.velocities=[]
self.anglecoef=[]
self.bondcoef=[]
self.dihedralcoef=[]
self.impropercoef=[]
self.paircoef=[]
self.read(file)
def read(self,file):
"""Reads in lammps data file
Skips the first line of the file (Comment line)
First reads the header portion of the file (sectflag=1)
blank lines are skipped
header keywords delineate an assignment
if no header keyword is found, body portion begins
Second reads the body portion of the file (sectflag=2)
first line of a section has only a keyword
next line is skipped
remaining lines contain values
a blank line signifies the end of that section
if no value is listed on a line than a keyword must be used
File is read until the end
The keywords read in are stored in self.keywords"""
if file=='':
print 'no file is given. Will have to build keywords and class structures manually'
return
sectflag=1
f=open(file,'r')
f.readline()
for line in f:
row=line.split()
if sectflag==1:
if len(row)==0:
#skip line the line is blank
pass
elif len(row)==1:
# Set Sectflag to 2, assume line is a keyword
sectflag=2
checkkey=1 #ensures keyword will be checked in body portion
keyword=row
elif len(row)==2:
if row[1]=='atoms':
self.atomnum=row[0]
self.keywords.append('atoms')
elif row[1]=='bonds':
self.bondnum=row[0]
self.keywords.append('bonds')
elif row[1]=='angles':
self.anglenum=row[0]
self.keywords.append('angles')
elif row[1]=='dihedrals':
self.dihedralnum=row[0]
self.keywords.append('dihedrals')
elif row[1]=='impropers':
self.impropernum=row[0]
self.keywords.append('impropers')
else:
# Set Sectflag to 2, assume line is a keyword
sectflag=2
checkkey=1 #ensures keyword will be checked in body portion
keyword=row
elif len(row)==3:
if row[1]=='atom' and row[2]=='types':
self.atomtypenum=row[0]
self.keywords.append('atom types')
elif row[1]=='bond' and row[2]=='types':
self.bondtypenum=row[0]
self.keywords.append('bond types')
elif row[1]=='angle' and row[2]=='types':
self.angletypenum=row[0]
self.keywords.append('angle types')
elif row[1]=='dihedral' and row[2]=='types':
self.dihedraltypenum=row[0]
self.keywords.append('dihedral types')
elif row[1]=='improper' and row[2]=='types':
self.impropertypenum=row[0]
self.keywords.append('improper types')
else:
# Set Sectflag to 2, assume line is a keyword
sectflag=2
checkkey=1 #ensures keyword will be checked in body portion
keyword=row
elif len(row)==4:
if row[2]=='xlo' and row[3]=='xhi':
self.xdimension=[row[0], row[1]]
self.keywords.append('xlo xhi')
elif row[2]=='ylo' and row[3]=='yhi':
self.ydimension=[row[0], row[1]]
self.keywords.append('ylo yhi')
elif row[2]=='zlo' and row[3]=='zhi':
self.zdimension=[row[0], row[1]]
self.keywords.append('zlo zhi')
else:
# Set Sectflag to 2, assume line is a keyword
sectflag=2
checkkey=1 #ensures keyword will be checked in body portion
keyword=row
elif len(row)==5:
if row[1]=='extra' and row[2]=='bond' and row[3]=='per' and row[4]=='atom':
self.extrabonds=row[0]
self.keywords.append('extra bond per atom')
else:
# Set Sectflag to 2, assume line is a keyword
sectflag=2
checkkey=1 #ensures keyword will be checked in body portion
keyword=row
elif len(row)==6:
if row[3]=='xy' and row[4]=='xz' and row[5]=='yz':
self.tilt=[row[0], row[1], row[2]]
self.keywords.append('xy xz yz')
else:
# Set Sectflag to 2, assume line is a keyword
sectflag=2
checkkey=1 #ensures keyword will be checked in body portion
keyword=row
else:
# set sectflag to 2, assume line is a keyword
sectflag=2
checkkey=1 #ensures keyword will be checked in body portion
keyword=row
elif sectflag==2:
if checkkey==1:
if len(keyword)==1:
if keyword[0]=='Atoms' or keyword[0]=='Velocities' or keyword[0]=='Masses' or\
keyword[0]=='Shapes' or keyword[0]=='Dipoles' or keyword[0]=='Bonds' or\
keyword[0]=='Angles' or keyword[0]=='Dihedrals' or keyword[0]=='Impropers':
bodyflag=1
blanknum=0
self.keywords.append(keyword[0])
checkkey=0
else:
bodyflag=0
checkkey=0
elif len(keyword)==2:
if row[1]=='Coeffs' and (row[0]=='Pair' or row[0]=='Bond' or row[0]=='Angle' or\
row[0]=='Dihedral' or row[0]=='Improper'):#class 2 force field keywords not included
bodyflag=1
blanknum=0
self.keywords.append('{0} {1}'.format(keyword[0],keyword[1]))
checkkey=0
else:
bodyflag=0
checkkey=0
else:
#egnore line and set bodyflag=0
bodyflag=0
checkkey=0
if bodyflag==0: #bodyflag 0 means no body keyword has been found
if len(row)==1:
if row[0]=='Atoms' or row[0]=='Velocities' or row[0]=='Masses' or\
row[0]=='Shapes' or row[0]=='Dipoles' or row[0]=='Bonds' or\
row[0]=='Angles' or row[0]=='Dihedrals' or row[0]=='Impropers':
bodyflag=1
blanknum=0
keyword=row
self.keywords.append(keyword[0])
else:
#egnore line
pass
elif len(row)==2:
if row[1]=='Coeffs' and (row[0]=='Pair' or row[0]=='Bond' or row[0]=='Angle' or\
row[0]=='Dihedral' or row[0]=='Improper'):#class 2 force field keywords not included
bodyflag=1
blanknum=0
keyword=row
self.keywords.append('{0} {1}'.format(keyword[0],keyword[1]))
else:
#egnore line
pass
else:
#egnore line
pass
elif bodyflag==1: #currently assumes 1 or more blank lines are between body data keywords
if len(row)==0:
blanknum+=1
if blanknum>1:
bodyflag=0
elif len(keyword)==1:
if keyword[0]=='Atoms':
try:
int(row[0])
except ValueError:
keyword=row
checkkey=1
else:
self.atoms.append(row)
elif keyword[0]=='Velocities':
try:
int(row[0])
except ValueError:
keyword=row
checkkey=1
else:
self.velocities.append(row)
elif keyword[0]=='Masses':
try:
int(row[0])
except ValueError:
keyword=row
checkkey=1
else:
self.masses.append(row)
elif keyword[0]=='Shapes':
try:
int(row[0])
except ValueError:
keyword=row
checkkey=1
else:
self.shapes.append(row)
elif keyword[0]=='Dipoles':
try:
int(row[0])
except ValueError:
keyword=row
checkkey=1
else:
self.dipoles.append(row)
elif keyword[0]=='Bonds':
try:
int(row[0])
except ValueError:
keyword=row
checkkey=1
else:
self.bonds.append(row)
elif keyword[0]=='Angles':
try:
int(row[0])
except ValueError:
keyword=row
checkkey=1
else:
self.angles.append(row)
elif keyword[0]=='Dihedrals':
try:
int(row[0])
except ValueError:
keyword=row
checkkey=1
else:
self.dihedrals.append(row)
elif keyword[0]=='Impropers':
try:
int(row[0])
except ValueError:
keyword=row
checkkey=1
else:
self.impropers.append(row)
else:
#egnore line and change bodyflag to 0
bodyflag=0
elif len(keyword)==2:
if keyword[0]=='Pair' and keyword[1]=='Coeffs':
try:
int(row[0])
except ValueError:
keyword=row
checkkey=1
else:
self.paircoef.append(row)
elif keyword[0]=='Bond' and keyword[1]=='Coeffs':
try:
int(row[0])
except ValueError:
keyword=row
checkkey=1
else:
self.bondcoef.append(row)
elif keyword[0]=='Angle' and keyword[1]=='Coeffs':
try:
int(row[0])
except ValueError:
keyword=row
checkkey=1
else:
self.anglecoef.append(row)
elif keyword[0]=='Dihedral' and keyword[1]=='Coeffs':
try:
int(row[0])
except ValueError:
keyword=row
checkkey=1
else:
self.dihedralcoef.append(row)
elif keyword[0]=='Improper' and keyword[1]=='Coeffs':
try:
int(row[0])
except ValueError:
keyword=row
checkkey=1
else:
self.impropercoef.append(row)
else:
#egnore line and change bodyflag to 0
bodyflag=0
else:
#egnore line and change bodyflag to 0
bodyflag=0
f.close()
def write(self,file,modflag):
"""Write lammps data files using the lammps keywords and lammpsdata structures
writes first line of the file as a Comment line
if no modifications to any of the lammpsdata structures (modflag=0)
Use Keywords to write lammpsdata structures directly
if modifications to any of the lammpsdata structures (modflag=1)
Key Lammpsdata structures like atom numbers, coeficient numbers
need to be modified to match the other modified lammpsdata structures
This section will still use the keywords to write lammpsdata structures.
For all modflags, the code will write data to the file until all of the
keyword's data structures have been finished writing.
The keywords are stored in self.keywords"""
f=open(file,'w')
f.write('polymer data file\n')
for row in self.keywords:
if row=='atoms':
if modflag==0:
f.write('{0} {1}\n'.format(self.atomnum,row))
elif modflag==1:
f.write('{0} {1}\n'.format(len(self.atoms),row))
elif row=='bonds':
if modflag==0:
f.write('{0} {1}\n'.format(self.bondnum,row))
elif modflag==1:
f.write('{0} {1}\n'.format(len(self.bonds),row))
elif row=='angles':
if modflag==0:
f.write('{0} {1}\n'.format(self.anglenum,row))
elif modflag==1:
f.write('{0} {1}\n'.format(len(self.angles),row))
elif row=='dihedrals':
if modflag==0:
f.write('{0} {1}\n'.format(self.dihedralnum,row))
elif modflag==1:
f.write('{0} {1}\n'.format(len(self.dihedrals),row))
elif row=='impropers':
if modflag==0:
f.write('{0} {1}\n'.format(self.impropernum,row))
elif modflag==1:
f.write('{0} {1}\n'.format(len(self.impropers),row))
elif row=='atom types':
if modflag==0:
f.write('{0} {1}\n'.format(self.atomtypenum,row))
elif modflag==1:
f.write('{0} {1}\n'.format(len(self.masses),row))
elif row=='bond types':
if modflag==0:
f.write('{0} {1}\n'.format(self.bondtypenum,row))
elif modflag==1:
f.write('{0} {1}\n'.format(len(self.bondcoef),row))
elif row=='angle types':
if modflag==0:
f.write('{0} {1}\n'.format(self.angletypenum,row))
elif modflag==1:
f.write('{0} {1}\n'.format(len(self.anglecoef),row))
elif row=='dihedral types':
if modflag==0:
f.write('{0} {1}\n'.format(self.dihedraltypenum,row))
elif modflag==1:
f.write('{0} {1}\n'.format(len(self.dihedralcoef),row))
elif row=='improper types':
if modflag==0:
f.write('{0} {1}\n'.format(self.impropertypenum,row))
elif modflag==1:
f.write('{0} {1}\n'.format(len(self.impropercoef),row))
elif row=='xlo xhi':
f.write('{0} {1} {2}\n'.format(self.xdimension[0],self.xdimension[1],row))
elif row=='ylo yhi':
f.write('{0} {1} {2}\n'.format(self.ydimension[0],self.ydimension[1],row))
elif row=='zlo zhi':
f.write('{0} {1} {2}\n'.format(self.zdimension[0],self.zdimension[1],row))
elif row=='extra bond per atom':
f.write('{0} {1}\n'.format(self.extrabonds,row))
elif row=='xy xz yz':
f.write('{0} {1} {2} {3}\n'.format(self.tilt[0],self.tilt[1],self.tilt[2],row))
elif row=='Atoms':
f.write('\n{0}'.format(row)) #new line between header and body portion or two body keywords
f.write('\n') #new line between body keyword and body data
for line in self.atoms:
f.write('\n') #creates a new line for adding body data
for item in line:
f.write(' {0}'.format(item)) #adds in each peice of body data with space imbetween
f.write('\n') #allows space to be added between the end of body data and a new keyword
elif row=='Velocities':
f.write('\n{0}'.format(row)) #new line between header and body portion or two body keywords
f.write('\n') #new line between body keyword and body data
for line in self.velocities:
f.write('\n') #creates a new line for adding body data
for item in line:
f.write(' {0}'.format(item)) #adds in each peice of body data with space imbetween
f.write('\n') #allows space to be added between the end of body data and a new keyword
elif row=='Masses':
f.write('\n{0}'.format(row)) #new line between header and body portion or two body keywords
f.write('\n') #new line between body keyword and body data
for line in self.masses:
f.write('\n') #creates a new line for adding body data
for item in line:
f.write(' {0}'.format(item)) #adds in each peice of body data with space imbetween
f.write('\n') #allows space to be added between the end of body data and a new keyword
elif row=='Shapes':
f.write('\n{0}'.format(row)) #new line between header and body portion or two body keywords
f.write('\n') #new line between body keyword and body data
for line in self.shapes:
f.write('\n') #creates a new line for adding body data
for item in line:
f.write(' {0}'.format(item)) #adds in each peice of body data with space imbetween
f.write('\n') #allows space to be added between the end of body data and a new keyword
elif row=='Dipoles':
f.write('\n{0}'.format(row)) #new line between header and body portion or two body keywords
f.write('\n') #new line between body keyword and body data
for line in self.dipoles:
f.write('\n') #creates a new line for adding body data
for item in line:
f.write(' {0}'.format(item)) #adds in each peice of body data with space imbetween
f.write('\n') #allows space to be added between the end of body data and a new keyword
elif row=='Bonds':
f.write('\n{0}'.format(row)) #new line between header and body portion or two body keywords
f.write('\n') #new line between body keyword and body data
for line in self.bonds:
f.write('\n') #creates a new line for adding body data
for item in line:
f.write(' {0}'.format(item)) #adds in each peice of body data with space imbetween
f.write('\n') #allows space to be added between the end of body data and a new keyword
elif row=='Angles':
f.write('\n{0}'.format(row)) #new line between header and body portion or two body keywords
f.write('\n') #new line between body keyword and body data
for line in self.angles:
f.write('\n') #creates a new line for adding body data
for item in line:
f.write(' {0}'.format(item)) #adds in each peice of body data with space imbetween
f.write('\n') #allows space to be added between the end of body data and a new keyword
elif row=='Dihedrals':
f.write('\n{0}'.format(row)) #new line between header and body portion or two body keywords
f.write('\n') #new line between body keyword and body data
for line in self.dihedrals:
f.write('\n') #creates a new line for adding body data
for item in line:
f.write(' {0}'.format(item)) #adds in each peice of body data with space imbetween
elif row=='Impropers':
f.write('\n{0}'.format(row)) #new line between header and body portion or two body keywords
f.write('\n') #new line between body keyword and body data
for line in self.impropers:
f.write('\n') #creates a new line for adding body data
for item in line:
f.write(' {0}'.format(item)) #adds in each peice of body data with space imbetween
f.write('\n') #allows space to be added between the end of body data and a new keyword
elif row=='Pair Coeffs':
f.write('\n{0}'.format(row)) #new line between header and body portion or two body keywords
f.write('\n') #new line between body keyword and body data
for line in self.paircoef:
f.write('\n') #creates a new line for adding body data
for item in line:
f.write(' {0}'.format(item)) #adds in each peice of body data with space imbetween
f.write('\n') #allows space to be added between the end of body data and a new keyword
elif row=='Bond Coeffs':
f.write('\n{0}'.format(row)) #new line between header and body portion or two body keywords
f.write('\n') #new line between body keyword and body data
for line in self.bondcoef:
f.write('\n') #creates a new line for adding body data
for item in line:
f.write(' {0}'.format(item)) #adds in each peice of body data with space imbetween
f.write('\n') #allows space to be added between the end of body data and a new keyword
elif row=='Angle Coeffs':
f.write('\n{0}'.format(row)) #new line between header and body portion or two body keywords
f.write('\n') #new line between body keyword and body data
for line in self.anglecoef:
f.write('\n') #creates a new line for adding body data
for item in line:
f.write(' {0}'.format(item)) #adds in each peice of body data with space imbetween
f.write('\n') #allows space to be added between the end of body data and a new keyword
elif row=='Dihedral Coeffs':
f.write('\n{0}'.format(row)) #new line between header and body portion or two body keywords
f.write('\n') #new line between body keyword and body data
for line in self.dihedralcoef:
f.write('\n') #creates a new line for adding body data
for item in line:
f.write(' {0}'.format(item)) #adds in each peice of body data with space imbetween
f.write('\n') #allows space to be added between the end of body data and a new keyword
elif row=='Improper Coeffs':
f.write('\n{0}'.format(row)) #new line between header and body portion or two body keywords
f.write('\n') #new line between body keyword and body data
for line in self.impropercoef:
f.write('\n') #creates a new line for adding body data
for item in line:
f.write(' {0}'.format(item)) #adds in each peice of body data with space imbetween
f.write('\n') #allows space to be added between the end of body data and a new keyword
else:
pass
f.close()
def atomorder(self):
"""Takes self.atoms and organizes the atom id from least to greatest.
If the atom ids are allready ordered this algorithm will do nothing."""
current=range(len(self.atoms[0])) # initialize current [assumes self.atoms coloumn #'s does not change]
for i in range(1,len(self.atoms)): #when i=0, self.atoms will not change; therefore its skipped
for k in range(len(self.atoms[i])):
current[k]=self.atoms[i][k]
for j in range(i-1,-1,-1):
for k in range(len(self.atoms[j])):
self.atoms[j+1][k]=self.atoms[j][k]
if int(current[0]) > int(self.atoms[j][0]):
for k in range(len(current)):
self.atoms[j+1][k]=current[k]
break
elif j==0:
for k in range(len(current)):
self.atoms[j][k]=current[k]
#dont need a break here because this is the last j value in the for loop
def addatoms(self, atoms, retlist=False):
"""Appends atoms to self.atoms. Assumes atoms are written in the correct atomtype format.
Change added atom numbers in self.atoms so self.atoms will be in increasing sequential order.
If retlist is True return a list of the modified atom numbers otherwise exit."""
initpos=len(self.atoms) #Store index of first appended atoms
for item in atoms:
self.atoms.append(range(len(item))) #initializing spots for the new atoms to go
numberchange=[] #initiate number change where the changed atom numbers will be stored
count=0
for i in range(initpos,len(self.atoms)):
for j in range(len(self.atoms[i])):
if j==0:
self.atoms[i][0]=str(i+1)
numberchange.append(str(i+1))
else:
self.atoms[i][j]=atoms[count][j]
count+=1
if retlist: return numberchange
else: return #need to redo this algorithm so their is no referencing going on.
def adddata(self,data,keyword):
"""Adds data to a keyword's existing data structure
All body keywords are viable except Atoms which has its own method
All header keywords will do nothing in this algrorithm because they have their own algorithm
changes the body id number so id numbers will be in sequential order"""
if keyword=='Velocities':
pos=len(self.velocities)
for item in data:
self.velocities.append(item) #adds data to existing data structure
self.velocities[pos][0]=str(pos+1) #changing body id number
pos+=1
elif keyword=='Masses':
pos=len(self.masses)
for item in data:
self.masses.append(item) #adds data to existing data structure
self.masses[pos][0]=str(pos+1) #changing body id number
pos+=1
elif keyword=='Shapes':
pos=len(self.shapes)
for item in data:
self.shapes.append(item) #adds data to existing data structure
self.shapes[pos][0]=str(pos+1) #changing body id number
pos+=1
elif keyword=='Dipoles':
pos=len(self.dipoles)
for item in data:
self.dipoles.append(item) #adds data to existing data structure
self.dipoles[pos][0]=str(pos+1) #changing body id number
pos+=1
elif keyword=='Bonds':
pos=len(self.bonds)
for item in data:
self.bonds.append(item) #adds data to existing data structure
self.bonds[pos][0]=str(pos+1)
pos+=1
elif keyword=='Angles':
pos=len(self.angles)
for item in data:
self.angles.append(item) #adds data to existing data structure
self.angles[pos][0]=str(pos+1) #changing body id number
pos+=1
elif keyword=='Dihedrals':
pos=len(self.dihedrals)
for item in data:
self.dihedrals.append(item) #adds data to existing data structure
self.dihedrals[pos][0]=str(pos+1) #changing body id number
pos+=1
elif keyword=='Impropers':
pos=len(self.impropers)
for item in data:
self.impropers.append(item) #adds data to existing data structure
self.impropers[pos][0]=str(pos+1) #changing body id number
pos+=1
elif keyword=='Pair Coeffs':
pos=len(self.paircoef)
for item in data:
self.paircoef.append(item) #adds data to existing data structure
self.paircoef[pos][0]=str(pos+1) #changing body id number
pos+=1
elif keyword=='Bond Coeffs':
pos=len(self.bondcoef)
for item in data:
self.bondcoef.append(item) #adds data to existing data structure
self.bondcoef[pos][0]=str(pos+1) #changing body id number
pos+=1
elif keyword=='Angle Coeffs':
pos=len(self.anglecoef)
for item in data:
self.anglecoef.append(item) #adds data to existing data structure
self.anglecoef[pos][0]=str(pos+1) #changing body id number
pos+=1
elif keyword=='Dihedral Coeffs':
pos=len(self.dihedralcoef)
for item in data:
self.dihedralcoef.append(item) #adds data to existing data structure
self.dihedralcoef[pos][0]=str(pos+1) #changing body id number
pos+=1
elif keyword=='Improper Coeffs':
pos=len(self.impropercoef)
for item in data:
self.impropercoef.append(item) #adds data to existing data structure
self.impropercoef[pos][0]=str(pos+1) #changing body id number
pos+=1
# def modifiydata(data,keyword): Will not implement
# """for modifying header data"""
def changeatomnum(self,data,originalatoms,atomchanges,vflag=False):
"""Takes data which contains atom ids
and alters those ids from the original atom id system in originalatoms
to the new atom id system in atomchanges."""
#set up boolean array to match the size of data and with all True values
# print atomchanges
array=booleanarray(len(data),len(data[0]),True)
# print originalatoms
if vflag: # for changing atomnumbers for velocities
for i in range(len(originalatoms)): #len of originalatoms should match len of atomchanges
if originalatoms[i][0]==atomchanges[i]: continue
for j in range(len(data)):
for k in range(1):
if data[j][k]==originalatoms[i][0]: #checks if the atom id in data
#matches the atom id in origianalatoms
if array.getelement(j,k): #if the boolean array is true
#set the boolean array to False and
#change the atom id in data to atomchanges
array.setelement(j,k,False)
data[j][k]=atomchanges[i]
break
#the change of boolean array to False insures
#the atom id in data will only be changed once.
else: # for changing atom numbers for everything else
for i in range(len(originalatoms)): #len of originalatoms should match len of atomchanges
if originalatoms[i][0]==atomchanges[i]: continue
for j in range(len(data)):
for k in range(2,len(data[j])):
if data[j][k]==originalatoms[i][0]: #checks if the atom id in data
#matches the atom id in origianalatoms
if array.getelement(j,k): #if the boolean array is true
#set the boolean array to False and
#change the atom id in data to atomchanges
array.setelement(j,k,False)
data[j][k]=atomchanges[i]
break
#the change of boolean array to False insures
#the atom id in data will only be changed once.
# print data
return data
def deletebodydata(self,keyword):
"""Changes a keyword's class data structure to an empty structure"""
if keyword=='Velocities':
self.velocities=[]
elif keyword=='Masses':
self.masses=[]
elif keyword=='Shapes':
self.shapes=[]
elif keyword=='Dipoles':
self.dipoles=[]
elif keyword=='Bonds':
self.bonds=[]
elif keyword=='Angles':
self.angles=[]
elif keyword=='Dihedrals':
self.dihedrals=[]
elif keyword=='Impropers':
self.impropers=[]
elif keyword=='Pair Coeffs':
self.paircoef=[]
elif keyword=='Bond Coeffs':
self.bondcoef=[]
elif keyword=='Angle Coeffs':
self.anglecoef=[]
elif keyword=='Dihedral Coeffs':
self.dihedralcoef=[]
elif keyword=='Improper Coeffs':
self.impropercoef=[]
elif keyword=='Atoms':
self.atoms=[]
def extractmolecules(self,molecule):
"""Takes the variable molecule and
extracts the individual molecules' data back into lmpsdata.
This extraction takes place through a 4 step process.
Step 1: Use a molecule's keywords to alter the lmpsdata data structures to empty.
To acomplish this procedure use the lmpsdata method deletebodydata.
Step 2: Add the molecules' atoms to lmpsdata's atoms using the method addatoms.
Return a list of atom id changes for each molecule.
Step 3: Utilize each molecules list of atom id changes to change their data's atom id numbers.
Uses changeatomnum and returns the altered molecule's data.
Step 4: Add the altered molecules' data to lmpsdata's data using the method adddata"""
#Use molecule index 0's keyword to change the equivalent lmpsdata structures to empty
print 'extracting the molecules back to data'
for keyword in molecule[0].keywords: # step 1
self.deletebodydata(keyword)
atomchanges=[] #initializing step 2
for i in range(len(molecule)): # step 2
atomchanges.append(self.addatoms(molecule[i].atoms,True))
for i in range(len(molecule)): # step 3
for keyword in molecule[i].keywords:
if keyword=='Angles':
molecule[i].angles=self.changeatomnum(molecule[i].angles,molecule[i].atoms,atomchanges[i])
if keyword=='Bonds':
molecule[i].bonds=self.changeatomnum(molecule[i].bonds,molecule[i].atoms,atomchanges[i])
elif keyword=='Dihedrals':
molecule[i].dihedrals=self.changeatomnum(molecule[i].dihedrals,molecule[i].atoms,atomchanges[i])
elif keyword=='Velocities':
molecule[i].velocities=self.changeatomnum(molecule[i].velocities,molecule[i].atoms,atomchanges[i],True)
elif keyword=='Impropers':
molecule[i].impropers=self.changeatomnum(molecule[i].impropers,molecule[i].atoms,atomchanges[i])
for i in range(len(molecule)): # step 4
for keyword in molecule[i].keywords:
if keyword=='Angles':
self.adddata(molecule[i].angles,keyword)
elif keyword=='Bonds':
self.adddata(molecule[i].bonds,keyword)
elif keyword=='Dihedrals':
self.adddata(molecule[i].dihedrals,keyword)
elif keyword=='Velocities':
self.adddata(molecule[i].velocities,keyword)
elif keyword=='Impropers':
self.adddata(molecule[i].impropers,keyword)
def density(self,ringsize,init,final,file=' '):
"""Create spherical shells from the initial radius to the final radius
The spherical shell's thickness is defined by ringsize
Calculate the mass of particles within each spherical shell
Calculate the volume of each spherical shell
Then calculate the density in each spherical shell
Current code is written with the assumption the spheres are centered around the origin
If a file is listed place the results in the variable file otherwise return the results
The distance calculations are written assuming image flags are in the data file"""
rho=[]
r=[init] #initial radius to examine
radius=init+ringsize
while radius<final: #finding the rest of the radii to examine
r.append(radius)
radius+=ringsize
for radius in r:
volume=4.0/3.0*3.1416*((radius+ringsize)**3 - radius**3)
mass=0.0
for row in self.atoms:
if self.atomtype=='angle' or self.atomtype=='atomic' or self.atomtype=='bond' or\
self.atomtype=='charge' or self.atomtype=='colloid' or self.atomtype=='electron' or\
self.atomtype=='full' or self.atomtype=='granular' or self.atomtype=='molecular' or\
self.atomtype=='peri':
l=len(row)-1
dist=float(row[l-3])**2+float(row[l-4])**2+float(row[l-5])**2
if dist<(radius+ringsize)**2 and dist>=radius**2:
if self.atomtype=='atomic' or self.atomtype=='charge' or\
self.atomtype=='colloid' or self.atomtype=='electron' or\
self.atomtype=='granular' or self.atomtype=='peri':
type=int(row[1])-1
else:
type=int(row[2])-1
mass+=float(self.masses[type][1])
#assumes self.masses is written in atomtype order
elif self.atomtype=='dipole':
l=len(row)-1
dist=float(row[l-6])**2+float(row[l-7])**2+float(row[l-8])**2
if dist<(radius+ringsize)**2 and dist>=radius**2:
type=int(row[1])-1
mass+=float(self.masses[type][1])
#assumes self.masses is written in atomtype order
elif self.atomtype=='ellipsoid':
l=len(row)-1
dist=float(row[l-7])**2+float(row[l-8])**2+float(row[l-9])**2
if dist<(radius+ringsize)**2 and dist>=radius**2:
type=int(row[1])
mass+=float(self.masses[type][1])
#assumes self.masses is written in atomtype order
elif self.atomtype=='hybrid':
dist=float(row[2])**2+float(row[3])**2+float(row[4])**2
if dist<(radius+ringsize)**2 and dist>=radius**2:
type=int(row[1])
mass+=float(self.masses[type][1])
#assumes self.masses is written in atomtype order
rho.append(mass/volume)
if file==' ':
return r,rho
else:
f=open(file,'w')
for i in range(len(r)):
f.write('{0} {1}\n'.format(r[i],rho[i]))
f.close()
return
def createxyz(self,file, routine='mass', values=None):
"""Two possible routines one to use the masses from data and the other to use the atom type and values supplied by the user.
The mass version is assessed by setting the routine to 'mass' which is the default method.
The other version is assessed by setting the routine to 'atomtype'.
The other version takes values which is a list containing the value the user wants to assign those atomtypes to.
The atomtypes of the values in the list will start at 1 even if no atoms in molecule use 1.
This makes it easier to find the atomtype and assign the value from the list
All atom data is assumed to have image flags in the data."""
f=open(file,'w')
f.write('{0}\n'.format(len(self.atoms)))
f.write('atoms\n')
if routine=='mass':
for line in self.atoms:
if self.atomtype=='angle' or self.atomtype=='bond' or self.atomtype=='full' or\
self.atomtype=='molecular':
type=int(line[2])-1 #3rd position
else:
type=int(line[1])-1 #2nd position
mass=self.masses[type][1]
if mass=='12.0107': elementnum=6
elif mass=='15.9994': elementnum=8
elif mass=='26.9815':elementnum=13
else:
print 'no matching mass value. The method will exit'
return
l=len(line)-1
if self.atomtype=='angle' or self.atomtype=='atomic' or self.atomtype=='bond' or\
self.atomtype=='charge' or self.atomtype=='colloid' or self.atomtype=='electron' or\
self.atomtype=='full' or self.atomtype=='granular' or self.atomtype=='molecular' or\
self.atomtype=='peri':
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[l-5],line[l-4],line[l-3]))
elif self.atomtype=='dipole':
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[l-8],line[l-7],line[l-6]))
elif self.atomtype=='ellipsoid':
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[l-9],line[l-8],line[l-7]))
elif self.atomtype=='hybrid':
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[2],line[3],line[4]))
f.close()
elif routine=='atomtype':
for line in self.atoms:
if self.atomtype=='angle' or self.atomtype=='bond' or self.atomtype=='full' or\
self.atomtype=='molecular':
type=int(line[2])-1 #3rd position
else:
type=int(line[1])-1 #2nd position
elementnum=values[type]
l=len(line)-1
if self.atomtype=='angle' or self.atomtype=='atomic' or self.atomtype=='bond' or\
self.atomtype=='charge' or self.atomtype=='colloid' or self.atomtype=='electron' or\
self.atomtype=='full' or self.atomtype=='granular' or self.atomtype=='molecular' or\
self.atomtype=='peri':
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[l-5],line[l-4],line[l-3]))
elif self.atomtype=='dipole':
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[l-8],line[l-7],line[l-6]))
elif self.atomtype=='ellipsoid':
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[l-9],line[l-8],line[l-7]))
elif self.atomtype=='hybrid':
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[2],line[3],line[4]))
f.close()
class booleanarray:
"""A class that stores boolean values in a list of lists."""
def __init__(self,rownum, colnum, initval):
""" initialise a list of lists (array) with
rownum correspondinig to the number of lists in the list and
colnum corresponding to the number of elements in the list's list.
initval is the value the list of lists will be initialized with.
initval should be a boolean value."""
# initializing self.array
self.array=[]
for i in range(rownum):
self.array.append(range(colnum))
# setting elements of self.array to initval
for i in range(rownum):
for j in range(colnum):
self.setelement(i,j,initval)
def setelement(self,rownum, colnum, value):
"""Assigns value to the list of lists (array) element at rownum and colnum."""
self.array[rownum][colnum]=value
def getelement(self,rownum,colnum):
"""Returns element in the list of lists (array) at rownum and colnum."""
return self.array[rownum][colnum]
def atomdistance(a,b,atomtype):
"""Returns the distance between atom a and b.
Atomtype is the style the atom data is written in.
All atom data is assumed to have image flags in the data.
Atom a and atom b are assumed to be the same atomtype."""
from math import sqrt
if atomtype=='angle' or atomtype=='atomic' or atomtype=='bond' or\
atomtype=='charge' or atomtype=='colloid' or atomtype=='electron' or\
atomtype=='full' or atomtype=='granular' or atomtype=='molecular' or\
atomtype=='peri':
l=len(a)-1
dist=sqrt((float(a[l-3])-float(b[l-3]))**2\
+(float(a[l-4])-float(b[l-4]))**2\
+(float(a[l-5])-float(b[l-5]))**2)
elif atomtype=='dipole':
l=len(a)-1
dist=sqrt((float(a[l-6])-float(b[l-6]))**2\
+(float(a[l-7])-float(b[l-7]))**2\
+(float(a[l-8])-float(b[l-8]))**2)
elif atomtype=='ellipsoid':
l=len(a)-1
dist=sqrt((float(a[l-7])-float(b[l-7]))**2\
+(float(a[l-8])-float(b[l-8]))**2\
+(float(a[l-9])-float(b[l-9]))**2)
elif atomtype=='hybrid':
dist=sqrt((float(a[2])-float(b[2]))**2\
+(float(a[3])-float(b[3]))**2\
+(float(a[4])-float(b[4]))**2)
return dist
def distance(a,coord,atomtype):
"""Returns the distance between atom a and coord.
Atomtype is the style the atom data is written in.
All atom data is assumed to have image flags in the data."""
from math import sqrt #need to alter this slightly
if atomtype=='angle' or atomtype=='atomic' or atomtype=='bond' or\
atomtype=='charge' or atomtype=='colloid' or atomtype=='electron' or\
atomtype=='full' or atomtype=='granular' or atomtype=='molecular' or\
atomtype=='peri':
l=len(a)-1
dist=sqrt((float(a[l-3])-coord[2])**2\
+(float(a[l-4])-coord[1])**2\
+(float(a[l-5])-coord[0])**2)
elif atomtype=='dipole':
l=len(a)-1
dist=sqrt((float(a[l-6])-coord[2])**2\
+(float(a[l-7])-coord[1])**2\
+(float(a[l-8])-coord[0])**2)
elif atomtype=='ellipsoid':
l=len(a)-1
dist=sqrt((float(a[l-7])-coord[2])**2\
+(float(a[l-8])-coord[1])**2\
+(float(a[l-9])-coord[0])**2)
elif atomtype=='hybrid':
dist=sqrt((float(a[2])-coord[0])**2\
+(float(a[3])-coord[1])**2\
+(float(a[4])-coord[0])**2)
return dist
class particlesurface:
def __init__(self,particle,cutoff,atomid,atomtype,shape='sphere'):
"""Builds a particle surface with a specific shape from a particle
The atoms choosen from the surface will have the specific atomid
atomid will be given in terms of an integer and not a string."""
self.particle=particle.atoms
self.atomtype=atomtype
self.cutoff=cutoff
self.surface=[]
self.particlelocator=[] #stores surface particle locations with respect to the particle
self.deletedatoms=[]
if shape=='sphere': self.createspheresurf(atomid)
def createspheresurf(self,atomid):
"""Assumes sphere is centered around 0,0,0.
Finds maximum distance particle with atomid.
Than all atoms within cutoff distance of max distance
will be included into self.surface
Also will build a list of where the surface particles are
in relationship to the particle.
Will create a booleanarray to keep track of any changes made to the surface."""
particledist=[]
for row in self.particle: #Stores all of the distances of the particle in particledist
if self.atomtype=='angle' or self.atomtype=='bond' or self.atomtype=='full' or\
self.atomtype=='molecular':
type=int(row[2]) #3rd position
else:
type=int(row[1]) #2nd position
if type==atomid: #only calculates the distance if the atom has the correct atomid number
particledist.append(distance(row,[0,0,0],self.atomtype))
else:
particledist.append(0.0)
self.maxdist=max(particledist)# finds the max dist.
for i in range(len(particledist)):
if particledist[i]>=(self.maxdist-self.cutoff):
self.particlelocator.append(i)
self.surface.append(self.particle[i])
self.bool=booleanarray(len(self.surface),1,True)
def getsurfatom(self,rownum):
return self.surface[rownum]
def getbool(self,rownum):
return self.bool.getelement(rownum,0)
def setbool(self,rownum,value):
self.bool.setelement(rownum,0,value)
def removesurfatom(self,rownum):
"""note this does not actually remove the surface atom.
Instead this adds a value to the list deletedatoms.
This list is later used in extractparticle to actually delete those atoms"""
self.deletedatoms.append(self.particlelocator[rownum])
def extractparticle(self):
""""deletesatoms from particle from the list of deletedatoms
and than returns the particle."""
self.particle=self.deleteatoms(self.particle,self.deletedatoms)
return self.particle
def deleteatoms(self,structure,rows):
"""delete atoms from particle and shifts the structure down"""
new=[]
#mulitple copying of b to the rows being replaced.
if rows==[]:
for line in structure:
new.append(line) #if no rows need replacing copy structure
return new
for i in range(rows[0]):
new.append(structure[i]) #copy structure to new until the first replaced row
count=0
for i in range(rows[0],len(structure)-len(rows)):# to replace rows and shift undeleted rows over
for j in range(i+1+count,len(structure)):
for val in rows:
if val==j:
count+=1
break
if val==j:continue
else:
new.append(structure[j])
break
return new
def addatom(self,atomtype,charge=None,moleculenum=None):
"""Adds an atom to the particle surface between maxdist and the cutoff distance.
This atom is stored in self.particle and self.surface.
In the current coding the particle is centered at (0,0,0).
This method has a required input of atomtype and optional inputs of charge and moleculenum.
This method currently does not support correctly self.atomtype of dipole, electron, ellipsoid, granular, peri or hybrid
Will use the image flags 0,0,0.
Note: The atomtype here is different from the atomtype attribute as part of this class
Note: If the added atom will be required for bonding later than you will need to extract the particle data
and rebuild the surface, because this method doesn't include updates to the required variables due to some coding issues"""
import math, random
# Checks to make sure self.atomtype is not set to an unsupported value
if self.atomtype=='dipole' or self.atomtype=='electron' or\
self.atomtype=='ellipsoid' or self.atomtype=='peri' or self.atomtype=='hybrid':
print self.atomtype, 'is not currently supported. But, you can add support by adding the needed functionality and inputs'
return
print 'adding an atom to the surface'
# Randomly assigns the position of a new atom in a spherical shell between self.cutoff and self.maxdist
foundpoint=False
while (foundpoint==False):
x=random.uniform(-self.maxdist,self.maxdist)
y=random.uniform(-self.maxdist,self.maxdist)
try:
z=random.uniform(math.sqrt(self.cutoff**2-x**2-y**2),math.sqrt(self.maxdist**2-x**2-y**2))
except ValueError:
continue
distance=math.sqrt(x**2+y**2+z**2)
if distance<self.maxdist and distance>=self.maxdist-self.cutoff:
foundpoint=True
# initialize new row in self.particle and self.surface
self.particle.append([])
self.surface.append([])
pposition=len(self.particle)-1 #particle postion
sposition=len(self.surface)-1 #surface position
# Adds the atom id number to the new row
self.particle[pposition].append(str(pposition+1))
self.surface[sposition].append(str(pposition+1))
# Adds the atomtype and the moleculenum if needed to the new row
if self.atomtype=='angle' or self.atomtype=='bond' or self.atomtype=='full' or\
self.atomtype=='molecular':
self.particle[pposition].append(str(moleculenum))
self.surface[sposition].append(str(moleculenum))
self.particle[pposition].append(str(atomtype))
self.surface[sposition].append(str(atomtype))
else:
self.particle[pposition].append(str(atomtype))
self.surface[sposition].append(str(atomtype))
# Adds the charge if needed to the new row
if self.atomtype=='charge' or self.atomtype=='full':
self.particle[pposition].append(str(charge))
self.surface[sposition].append(str(charge))
# Adds the atom's position to the new row
self.particle[pposition].append(str(x))
self.surface[sposition].append(str(x))
self.particle[pposition].append(str(y))
self.surface[sposition].append(str(y))
self.particle[pposition].append(str(z))
self.surface[sposition].append(str(z))
# Adds the atom's image flags to the new row
self.particle[pposition].append('0')
self.surface[sposition].append('0')
self.particle[pposition].append('0')
self.surface[sposition].append('0')
self.particle[pposition].append('0')
self.surface[sposition].append('0')
def createxyz(self,file,data,routine='mass', values=None):
"""This shows the particle surface. To show the particle surface after bonding has occured,
you will need to extract the particle than reinsert the particle into the class and use createxyz.
Two possible routines one to use the masses from data and the other to use the atom type and values supplied by the user.
The mass version is assessed by setting the routine to 'mass' which is the default method.
The other version is assessed by setting the routine to 'atomtype'.
The other version takes values which is a list containing the value the user wants to assign those atomtypes to.
The atomtypes of the values in the list will start at 1 even if no atoms in molecule use 1.
This makes it easier to find the atomtype and assign the value from the list
All atom data is assumed to have image flags in the data."""
f=open(file,'w')
f.write('{0}\n'.format(len(self.surface)))
f.write('atoms\n')
if routine=='mass':
for line in self.surface:
if self.atomtype=='angle' or self.atomtype=='bond' or self.atomtype=='full' or\
self.atomtype=='molecular':
type=int(line[2])-1 #3rd position
else:
type=int(line[1])-1 #2nd position
mass=data.masses[type][1]
if mass=='12.0107': elementnum=6
elif mass=='15.9994': elementnum=8
elif mass=='26.981539':elementnum=13
else:
print 'no matching mass value. The method will exit'
return
l=len(line)-1
if self.atomtype=='angle' or self.atomtype=='atomic' or self.atomtype=='bond' or\
self.atomtype=='charge' or self.atomtype=='colloid' or self.atomtype=='electron' or\
self.atomtype=='full' or self.atomtype=='granular' or self.atomtype=='molecular' or\
self.atomtype=='peri':
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[l-5],line[l-4],line[l-3]))
elif self.atomtype=='dipole':
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[l-8],line[l-7],line[l-6]))
elif self.atomtype=='ellipsoid':
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[l-9],line[l-8],line[l-7]))
elif self.atomtype=='hybrid':
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[2],line[3],line[4]))
f.close()
elif routine=='atomtype':
for line in self.surface:
if self.atomtype=='angle' or self.atomtype=='bond' or self.atomtype=='full' or\
self.atomtype=='molecular':
type=int(line[2])-1 #3rd position
else:
type=int(line[1])-1 #2nd position
elementnum=values[type]
l=len(line)-1
if self.atomtype=='angle' or self.atomtype=='atomic' or self.atomtype=='bond' or\
self.atomtype=='charge' or self.atomtype=='colloid' or self.atomtype=='electron' or\
self.atomtype=='full' or self.atomtype=='granular' or self.atomtype=='molecular' or\
self.atomtype=='peri':
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[l-5],line[l-4],line[l-3]))
elif self.atomtype=='dipole':
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[l-8],line[l-7],line[l-6]))
elif self.atomtype=='ellipsoid':
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[l-9],line[l-8],line[l-7]))
elif self.atomtype=='hybrid':
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[2],line[3],line[4]))
f.close()
def molecules(data,init,final,processors, method='all'):
""" There are two ways to initialize the class Lmpsmolecule.
Method controls which way is chosen.
Acceptable values for Method are 'all', 'atom'.
The default method is 'all'"""
molecule=[]
from multiprocessing import Pool
p=Pool(processors)
for i in range(init,final+1):
molecule.append(p.apply_async(Lmpsmolecule,(i,data,method,)))
for i in range(len(molecule)):
molecule[i]=molecule[i].get()
p.close()
p.join()
return molecule
class Lmpsmolecule: #Technically should be a meta class but written as a seperate class for easier coding.
def __init__(self,moleculenum,data,method):
"""initiates lammps molecule structures
and than extract the appropriate molecular structures from the base class data"""
# ***** Lammps Molecule Structures
self.keywords=['Atoms']#include atoms here since this will be in every instance of this class
self.atoms=[] #extract
self.angles=[] #extract if keyword is there
self.bonds=[] #extract if keyword is there
self.dihedrals=[] #extract if keyword is there
self.impropers=[] #extract if keyword is there
self.velocities=[] #extract if keyword is there
# ***** Molecule number
self.moleculenum=moleculenum
# ***** Extracting the moleculue's atom information from data
self.extract(data,method)
# ***** If methods is 'all' then self.extract will extract all of the molecule's information from data
def extract(self,data,method):
"""uses base class data to extract the molecules atoms
and any other molecule data from molecule moleculenum. This extraction is done in a two step process.
Step 1: extract data.atoms with moleculenum and renumber self.atoms beginning from 1
store extracted atom numbers from data.atoms in a list called temp
Step 2: pass temp and data to method changeatomnum
which extracts the rest of the Lammps Molecule structures from data
and changes the atomnumbers in those structures to match the ones already in self.atoms"""
#checking to make sure atomtype is a valid molecule
#if not a valid molecule print error and exit method
if data.atomtype=='full' or data.atomtype=='molecular':
# ***** Sets the molecule's atomtype
self.atomtype=data.atomtype
else:
print "not a valid molecular structure"
return
#extract the molecule self.moleculenum from data.atom to self.atom
atomnum=1
temp=[]
for i in range(len(data.atoms)):
if int(data.atoms[i][1])==self.moleculenum:
temp.append(data.atoms[i][0]) #store extracted atomnumbers into temp
self.atoms.append(data.atoms[i]) #store extracted atom into self.atom
self.atoms[atomnum-1][0]=str(atomnum) #change extracted atom to the correct atomnumber
atomnum+=1 #update atomnumber
#extract the rest of the Lammps Molecule structures from data using changeatomnum
if method=='atom':
return
else:
self.changeatomnum(temp,data)
def changeatomnum(self,temp,data=' '):
"""changes the atomnumbers in Lmpsmolecule structures angles, bonds, dihedrals, impropers,
and velocities in a three step process.
If data is defined extract the rest of the keywords used for Lmpsmolecule.
Step 1A:If data is defined copy from data one of the above structures.
If data is not defined skip this step.
Step 1B:If data is defined remove the rows of copy which do not contain any values from temp
Step 2: If data is defined extract from copy to an above Lmpsmolecule structure and remove the extracted rows
If data is not defined skip this step.
Step 3: Use temp and self.atoms to convert the atomnumbers in Lmpsmolecule structures
to the correct values.
temp and self.atoms line up, so temp[i] and self.atoms[i][0]
correspond to the current Lmpsmolecule structures atom numbers
and correct values
will use booleanarray class to ensure that lmpsmolecule's structure values are altered only once."""
#Step 1 and Step 2
if data!=' ':
#extract molecular keywords from data.keywords
for keywords in data.keywords:
if keywords=='Angles' or keywords=='Bonds' or keywords=='Dihedrals' or\
keywords=='Impropers' or keywords=='Velocities':
self.keywords.append(keywords)
for keywords in self.keywords:
if keywords!='Atoms': print 'extracting the data from', keywords
if keywords=='Angles':
copy=self.copy(data.angles) #Step 1A
dnr=[] #dnr means do not remove a 0 means remove and a 1 means keep
for j in range(len(copy)): #Step 1B
dnr.append(0) #adds 0 to all list elements of dnr
for item in temp: #finds copied structure that has temp values
for j in range(len(copy)):
for i in range(2,len(copy[j])):
if copy[j][i]==item:
dnr[j]=1 #changes jth list element of dnr to 1
break
remove=[]
for j in range(len(dnr)): # finds dnr values that are still 0
if dnr[j]==0:
remove.append(j) #and appends their index value to the list remove
copy=self.deleterows(copy,remove) #removes all unneeded rows from copy
structnum=1
print 'the length of data is', len(copy)
for item in temp: #Step 2
found=[]
for j in range(len(copy)):
for i in range(2,len(copy[j])):
if copy[j][i]==item:
found.append(j)
self.angles.append(copy[j])
l=len(self.angles)-1
self.angles[l][0]=str(structnum)
structnum+=1
break
# print 'the item is', item
# print 'found is', found
copy=self.deleterows(copy,found)
elif keywords=='Bonds':
copy=self.copy(data.bonds) #Step 1A
dnr=[] #dnr means do not remove a 0 means remove and a 1 means keep
for j in range(len(copy)): #Step 1B
dnr.append(0) #adds 0 to all list elements of dnr
for item in temp: #finds copied structure that has temp values
for j in range(len(copy)):
for i in range(2,len(copy[j])):
if copy[j][i]==item:
dnr[j]=1 #changes jth list element of dnr to 1
break
remove=[]
for j in range(len(dnr)): # finds dnr values that are still 0
if dnr[j]==0:
remove.append(j) #and appends their index value to the list remove
copy=self.deleterows(copy,remove) #removes all unneeded rows from copy
structnum=1
print 'the length of data is', len(copy)
for item in temp: #Step 2
found=[]
for j in range(len(copy)):
for i in range(2,len(copy[j])):
if copy[j][i]==item:
found.append(j)
self.bonds.append(copy[j])
l=len(self.bonds)-1
self.bonds[l][0]=str(structnum)
structnum+=1
break
# print 'the item is', item
# print 'found is', found
copy=self.deleterows(copy,found)
elif keywords=='Dihedrals':
copy=self.copy(data.dihedrals) #Step 1A
dnr=[] #dnr means do not remove a 0 means remove and a 1 means keep
for j in range(len(copy)): #Step 1B
dnr.append(0) #adds 0 to all list elements of dnr
for item in temp: #finds copied structure that has temp values
for j in range(len(copy)):
for i in range(2,len(copy[j])):
if copy[j][i]==item:
dnr[j]=1 #changes jth list element of dnr to 1
break
remove=[]
for j in range(len(dnr)): # finds dnr values that are still 0
if dnr[j]==0:
remove.append(j) #and appends their index value to the list remove
copy=self.deleterows(copy,remove) #removes all unneeded rows from copy
structnum=1
print 'the length of data is', len(copy)
structnum=1
for item in temp: #Step 2
found=[]
for j in range(len(copy)):
for i in range(2,len(copy[j])):
if copy[j][i]==item:
found.append(j)
self.dihedrals.append(copy[j])
l=len(self.dihedrals)-1
self.dihedrals[l][0]=str(structnum)
structnum+=1
break
# print 'the item is', item
# print 'found is', found
copy=self.deleterows(copy,found)
elif keywords=='Impropers':
copy=self.copy(data.impropers) #Step 1B
dnr=[] #dnr means do not remove a 0 means remove and a 1 means keep
for j in range(len(copy)): #Step 1B
dnr.append(0) #adds 0 to all list elements of dnr
for item in temp: #finds copied structure that has temp values
for j in range(len(copy)):
for i in range(2,len(copy[j])):
if copy[j][i]==item:
dnr[j]=1 #changes jth list element of dnr to 1
break
remove=[]
for j in range(len(dnr)): # finds dnr values that are still 0
if dnr[j]==0:
remove.append(j) #and appends their index value to the list remove
copy=self.deleterows(copy,remove) #removes all unneeded rows from copy
structnum=1
print 'the length of data is', len(copy)
for item in temp: #Step 2
found=[]
for j in range(len(copy)):
for i in range(2,len(copy[j])):
if copy[j][i]==item:
found.append(j)
self.impropers.append(copy[j])
l=len(self.impropers)-1
self.impropers[l][0]=str(structnum)
structnum+=1
break
# print 'the item is', item
# print 'found is', found
copy=self.deleterows(copy,found)
elif keywords=='Velocities':
copy=self.copy(data.velocities) #Step 1
dnr=[] #dnr means do not remove a 0 means remove and a 1 means keep
for j in range(len(copy)): #Step 1B
dnr.append(0) #adds 0 to all list elements of dnr
for item in temp: #finds copied structure that has temp values
for j in range(len(copy)):
for i in range(1):
if copy[j][i]==item:
dnr[j]=1 #changes jth list element of dnr to 1
break
remove=[]
for j in range(len(dnr)): # finds dnr values that are still 0
if dnr[j]==0:
remove.append(j) #and appends their index value to the list remove
copy=self.deleterows(copy,remove) #removes all unneeded rows from copy
structnum=1
print 'the length of data is', len(copy)
for item in temp: #Step 2
found=[]
for j in range(len(copy)):
for i in range(1):
if copy[j][i]==item:
found.append(j)
self.velocities.append(copy[j])
l=len(self.velocities)-1
self.velocities[l][0]=str(structnum)
structnum+=1
break
# print 'the item is', item
# print 'found is', found
copy=self.deleterows(copy,found)
#Step 3
for keywords in self.keywords:
if keywords!='Atoms': print 'altering data structure values for', keywords
if keywords=='Angles':
copy=self.copy(self.angles)
array=booleanarray(len(copy),len(copy[0]),True) #creating a booleanarray with true values
for i in range(len(temp)):
if temp[i]==self.atoms[i][0]: continue
for j in range(len(copy)):
for k in range(2,len(copy[j])):
if copy[j][k]==temp[i]:
if array.getelement(j,k): #if the boolean array is true
self.angles[j][k]=self.atoms[i][0]
array.setelement(j,k,False)
break
elif keywords=='Bonds':
copy=self.copy(self.bonds)
array=booleanarray(len(copy),len(copy[0]),True) #creating a booleanarray with true values
for i in range(len(temp)):
if temp[i]==self.atoms[i][0]: continue
for j in range(len(copy)):
for k in range(2,len(copy[j])):
if copy[j][k]==temp[i]:
if array.getelement(j,k): #if the boolean array is true
self.bonds[j][k]=self.atoms[i][0]
array.setelement(j,k,False)
break
elif keywords=='Dihedrals':
copy=self.copy(self.dihedrals)
array=booleanarray(len(copy),len(copy[0]),True) #creating a booleanarray with true values
for i in range(len(temp)):
if temp[i]==self.atoms[i][0]: continue
for j in range(len(copy)):
for k in range(2,len(copy[j])):
if copy[j][k]==temp[i]:
if array.getelement(j,k): #if the boolean array is true
self.dihedrals[j][k]=self.atoms[i][0]
array.setelement(j,k,False)
break
elif keywords=='Impropers':
copy=self.copy(self.impropers)
array=booleanarray(len(copy),len(copy[0]),True) #creating a booleanarray with true values
for i in range(len(temp)):
if temp[i]==self.atoms[i][0]: continue
for j in range(len(copy)):
for k in range(2,len(copy[j])):
if copy[j][k]==temp[i]:
if array.getelement(j,k): #if the boolean array is true
self.impropers[j][k]=self.atoms[i][0]
array.setelement(j,k,False)
break
elif keywords=='Velocities':
copy=self.copy(self.velocities)
array=booleanarray(len(copy),len(copy[0]),True) #creating a booleanarray with true values
for i in range(len(temp)):
if temp[i]==self.atoms[i][0]: continue
for j in range(len(copy)):
for k in range(1):
if copy[j][k]==temp[i]:
if array.getelement(j,k): #if the boolean array is true
self.velocities[j][k]=self.atoms[i][0]
array.setelement(j,k,False)
break
def copy(self,structure):
"""copies structure to same and returns same."""
same=[]
for row in structure:
same.append(row)
return same
def deleterows(self,structure,rows): # run through this {structure is list of strings and rows is list
#of numbers}
"""delete rows in a structure and shifts the structure up
rows must be in increasing order for this algorithm to work correctly"""
new=[]
#mulitple copying of b to the rows being replaced.
if rows==[]:
for line in structure:
new.append(line) #if no rows need replacing copy structure
return new
for i in range(rows[0]):
new.append(structure[i]) #copy structure to new until the first replaced row
count=0
for i in range(rows[0],len(structure)-len(rows)):# to replace rows and shift undeleted rows over
for j in range(i+1+count,len(structure)):
for val in rows:
if val==j:
count+=1
break
if val==j:continue
else:
new.append(structure[j])
break
return new
def modifyatom(self,atomnumber,column,newvalue):
"""modifies self.atom[atomnumber-1][column] to newvalue.
*note: newvalue needs to be a string
if column is 0 than changeatomnum method might need runnning for all atoms
that have had their atomnumber(column=0) modified.
changeatomnum method is not ran in this method when column=0"""
self.atoms[atomnumber-1][column]=newvalue
def deleteatoms(self,atomnumbers,atomid):
"""Algorithm to find all atoms bonded to atomnumbers in the direction of atomid.
Atomid can be a list or a single integer. The single integer corresponds to atom's atomtype value.
The list corresponds to the atom's atomid values. The only difference between both cases is in the top portion of code.
When all bonded atoms have been found; ie: (the modified return values from findbonds yields an empty list);
delete those bonded atoms and all molecule structures which contain those atoms.
Convert the list of bonded atoms into rows and delete those rows from molecule.atoms"""
print 'finding atoms to delete'
bondedatoms=[]
# 1st iteration
nextatoms=self.findbonds(atomnumbers)
try: # tests whether atomid is a list or a single integer
atomid[0]
except TypeError:
#need to remove atoms from nextatoms which dont have the proper atom id
testflag=True
i=0
while testflag:
if i>len(nextatoms)-1: break #For the case where i becomes greater than the len of nextatoms break loop
if int(self.atoms[nextatoms[i]-1][2])!=atomid:#uses the atom id for the row in atoms and than checks atom id
del nextatoms[i] #delets the atom at i
i-=1 #and than decreases i by 1 so next atom in the list will line up when i is increased
i+=1 #increase i by 1
else:
#need to remove atoms from nextatoms which dont have the proper atom id
testflag=True
i=0
while testflag:
if i>len(nextatoms)-1: break #For the case where i becomes greater than the len of nextatoms break loop
keep=False
for id in atomid:
if int(self.atoms[nextatoms[i]-1][0])==id: #checking if atomid is in next atom
keep=True #keep this atom
break
if not keep:
del nextatoms[i] #delets the atom at i
i-=1 #and than decreases i by 1 so next atom in the list will line up when i is increased
i+=1 #increase i by 1
#append next atoms into bondedatoms
#copy next atoms into prevatoms
prevatoms=[]
for atom in nextatoms:
bondedatoms.append(atom)
prevatoms.append(atom)
#2nd iteration
if prevatoms==[]:
print 'no bonds were found in first iteration that had atomid criteria'
return
nextatoms=self.findbonds(prevatoms)
#need to remove atoms from nextatoms which are in atomnumbers
for atom in atomnumbers:
for i in range(len(nextatoms)):
if nextatoms[i]==atom: #checking if atom is in next atom
del nextatoms[i] #delete the atom at i
break
if nextatoms==[]: break #all bonds from find bonds have allready been added to bondedatoms
#append next atoms into bondedatoms
#copy next atoms into prevatoms
prevatoms=[]
for atom in nextatoms:
bondedatoms.append(atom)
prevatoms.append(atom)
#iterative proccess for finding the rest of the atoms bonded to atomnumbers in the direction of atomid.
while prevatoms!=[]:
nextatoms=self.findbonds(prevatoms)
#need to remove atoms from nextatoms which are in the prevatoms
for atom in bondedatoms:
for i in range(len(nextatoms)):
if nextatoms[i]==atom: #checking if atom is in next atom
del nextatoms[i] #delete the atom at i
break
if nextatoms==[]: break #all bonds from find bonds have allready been added to bondedatoms
#append next atoms into bondedatoms
#copy next atoms into prevatoms
prevatoms=[]
for atom in nextatoms:
bondedatoms.append(atom)
prevatoms.append(atom)
print 'the atoms to delete are', bondedatoms
print 'deleting atoms from structures'
#delete bonded atoms from the molecule's structures except the atom structure
for i in range(1,len(self.keywords)): #goes through all keywords except the atom keyword
print self.keywords[i]
if self.keywords[i]=='Angles':
rows=self.findatomnumbers(bondedatoms,self.angles,False)
rows=self.listorder(rows) #to order the rows in increasing order
self.angles=self.deleterows(self.angles,rows) #requires that rows be in increasing order
elif self.keywords[i]=='Bonds':
rows=self.findatomnumbers(bondedatoms,self.bonds,False)
rows=self.listorder(rows) #to order the rows in increasing order
self.bonds=self.deleterows(self.bonds,rows)#requires that rows be in increasing order
elif self.keywords[i]=='Dihedrals':
rows=self.findatomnumbers(bondedatoms,self.dihedrals,False)
rows=self.listorder(rows) #to order the rows in increasing order
self.dihedrals=self.deleterows(self.dihedrals,rows) #requires that rows be in increasing order
elif self.keywords[i]=='Impropers':
rows=self.findatomnumbers(bondedatoms,self.impropers,False)
rows=self.listorder(rows) #to order the rows in increasing order
self.impropers=self.deleterows(self.impropers,rows) #requires that rows be in increasing order
elif self.keywords[i]=='Velocities':
rows=self.findatomnumbers(bondedatoms,self.velocities,True)
rows=self.listorder(rows) #to order the rows in increasing order
self.velocities=self.deleterows(self.velocities,rows) #requires that rows be in increasing order
print 'Atoms'
#convert bondedatoms from atom numbers to row numbers
for i in range(len(bondedatoms)):
bondedatoms[i]-=1
bondedatoms=self.listorder(bondedatoms) #to order the row numbers in increasing order
#delete bonded atoms (row numbers) from the atom structure
self.atoms=self.deleterows(self.atoms,bondedatoms) #requires that row numbers be in increasing order
def findatomnumbers(self,atomnumbers,structure,vflag): #need to read through this algorithm
"""Algorithm to find atomnumbers in a molecule structure except.
Atoms structure is not handled in here.
Returns a list of the rows in which the atomnumbers are contained in the molecule structure"""
rows=[]
if vflag: #for handling velocity structure
for atom in atomnumbers:
for i in range(len(structure)):
if int(structure[i][0])==atom:
#duplicate rows for vflag=True are not possible.
rows.append(i)
break
else: #for handling all other structures except atoms
for atom in atomnumbers:
for i in range(len(structure)):
for j in range(2,len(structure[i])):
if int(structure[i][j])==atom:
#need to make sure duplicate value of rows are not being added
if rows==[]:
rows.append(i) #appends the row number
else:
#checking for duplicate values of rows
duplicateflag=0
for k in range(len(rows)):
if rows[k]==i:
duplicateflag=1
break
if duplicateflag==0: #if no duplicates adds bond number
rows.append(i) #appends the row number
break
print 'the finished row is', rows
return rows
def listorder(self,struct):
"""Takes struct and organizes the list from least to greatest.
If the list is allready ordered this algorithm will do nothing."""
if len(struct)==1: return struct #with the length at 1; thier is only one element and theirfore nothing to order
for i in range(1,len(struct)): #when i=0, struct will not change; therefore its skipped
copy=struct[i]
for j in range(i-1,-1,-1):
struct[j+1]=struct[j]
if copy >struct[j]:
struct[j+1]=copy
break
elif j==0:
struct[j]=copy
#dont need a break here because this is the last j value in the for loop
print 'the organized row is', struct
return struct
def findbonds(self,atomnumbers):
"""Algorithm to find all atoms bonded to atomnumbers.
Returns a list of atomnumbers"""
#finds the bonds in which the atomnumbers are located
bondids=[]
for i in range(len(atomnumbers)):
for j in range(len(self.bonds)):
for k in range(2,len(self.bonds[j])):
if int(self.bonds[j][k])==atomnumbers[i]:
if bondids==[]:
bondids.append(int(self.bonds[j][0])) #appends the bond number
else:
#checking for duplicates of bondids
duplicateflag=0
for l in range(len(bondids)):
if bondids[l]==int(self.bonds[j][0]):
duplicateflag=1
break
if duplicateflag==0: #if no duplicates adds bond number
bondids.append(int(self.bonds[j][0]))
break
#Using bondids find the atoms bonded to atomnumbers
bondedatoms=[]
from math import fabs
for id in bondids:
for atoms in atomnumbers:
found=False
for i in range(2,len(self.bonds[id-1])):
if int(self.bonds[id-1][i])==atoms:
j=int(fabs(i-5)) #switches the index from the atomnumber location to the other location
bondedatoms.append(int(self.bonds[id-1][j])) #appends the atomnuber at the other location
found=True
break
if found==True: break
return bondedatoms
def findparticlebondingpoints(self,particle,atomid,cutoffdistance,bondnumber):
"""Particle is a particlesurfaceobject, atomid is an int.
Finds atoms with atomid in the molecule which are less than the cutoffdistance from atoms in the particle.
The found atoms and particles locations are stored in a 3 dimensional list called possiblebonds
The first index corresponds with the molecule's atom
The second index correspons with the molecule/particle combination
The third index corresponds with whether the value is the molecule or the particle
Always bonds the two ends of the molecule that meet cutoff requirement.
All other possible bonds are randomly choosen until the required bondnumbers are met.
After every bond is choosen, the particle object's boolean list is updated, and possiblebonds is updated.
The update to possiblebonds involves removing the row from which the bonded molecule's atom is located
and also removing the particle atom and it's corresponding bonded atom from other rows of possiblebonds.
The final bonds are all stored in self.bonding as a 2 dimensional list"""
possiblebonds=[]
for i in range(len(self.atoms)):
if int(self.atoms[i][2])==atomid:
row=[]
for j in range(len(particle.surface)):
#assumes molecule and particle have same atomtype if not true than atomdistance will give bad value
if atomdistance(self.atoms[i],particle.surface[j],self.atomtype)<=cutoffdistance:
if particle.getbool(j): row.append([i,j]) #if not bonded than can form a possible bond
if row!=[]:possiblebonds.append(row) #need to correct this....
#initiate section which assigns bonds into bonding information
bonds=0
self.bondinginformation=[] #initiate new class member
#Checks to see if no bonds are possible [2 possible cases]
if possiblebonds==[]:
print 'no possible bonds can be formed'
return
if bondnumber==0:
print 'bondnumber is 0; so, no possible bonds can form'
return
#section which assigns a bond to the first molecule atom which can be bonded.
self.bondinginformation.append(self.particlebondinginfo(particle,possiblebonds,0))
bonds+=1
if bonds==bondnumber: return
del possiblebonds[0] #deletes possible bonds to the first molecule which can be bonded
l=len(self.bondinginformation)-1
possiblebonds=self.updatepossiblebonds(possiblebonds,self.bondinginformation[l][1]) #updates possiblebonds
#by removing any bonds which contain the newly bonded particle.
if possiblebonds==[]:return
#section which finds the last molecule atom which can be bonded
l=len(possiblebonds)-1
while possiblebonds[l]==[]:# to find the last molecule atom which can be bonded
if possiblebonds==[]:return
del possiblebonds[l] #since there are no more possible bonds in this location delete
l-=1 #go to next possible spot where the last molecule atom could be bonded
#section which assigns a bond to the last molecule atom which can be bonded.
self.bondinginformation.append(self.particlebondinginfo(particle,possiblebonds,l))
bonds+=1
if bonds==bondnumber: return
del possiblebonds[l] #deletes possible bonds to the last molecule which can be bonded
l=len(self.bondinginformation)-1
possiblebonds=self.updatepossiblebonds(possiblebonds,self.bondinginformation[l][1])
if bondnumber-bonds>=len(possiblebonds): #the rest of the bonds are assigned in order
while possiblebonds!=[]:
if possiblebonds[0]==[]: #if row of possible bonds is empty then delete the row
del possiblebonds[0]
else: #else find a bond in the row of possible bonds
self.bondinginformation.append(self.particlebondinginfo(particle,possiblebonds,0))
#dont need to update bonds since possiblebonds will become empty at the same time or before bonds
#is equal to bondnumber
del possiblebonds[0]
l=len(self.bondinginformation)-1
possiblebonds=self.updatepossiblebonds(possiblebonds,self.bondinginformation[l][1])
return
else: #the rest of the bonds are assigned randomly
from random import randint #use to randomly choose an index to bond.
while bonds<bondnumber:
if possiblebonds==[]:break #exits while loop when possiblebonds has become an empty set.
#this ensures that in the case there are not egnough viable bonds from possiblebonds to
#reach the bondnumber. Than, the while loop will not become infinite.
l=len(possiblebonds)-1
i=randint(0,l)
if possiblebonds[i]==[]: #if row of possible bonds is empty then delete the row
del possiblebonds[i]
else: #else find a bond in the row of possible bonds
self.bondinginformation.append(self.particlebondinginfo(particle,possiblebonds,i))
bonds+=1
del possiblebonds[i]
l=len(self.bondinginformation)-1
possiblebonds=self.updatepossiblebonds(possiblebonds,self.bondinginformation[l][1])
return
def particlebondinginfo(self,particle,possiblebonds,index1):
"""Takes list of possiblebonds and assigns a bond from possiblebonds[index1].
Then assigns false to particle.setbool at the bonding location
to ensure no more bonds can form with that particle.
Returns the assigned bond."""
from random import randint #use to randomly choose 0 and 1 where 1 is keep.
for i in range(len(possiblebonds[index1])):
if i==len(possiblebonds[index1])-1: #automattically bonds under this condition
break
else: #bond has random chance of forming
if randint(0,1)==1: #bond forms
break
else: #no bond forms
continue
particle.setbool(possiblebonds[index1][i][1],False)#makes sure no more bonds can form
return possiblebonds[index1][i]
def updatepossiblebonds(self,possiblebonds,particlenum):
"""finds the particle number in the remaining possible bonds than deletes that bonding information.
This algorithm assumes that particlenum can exist only once in each row of possiblebonds."""
for i in range(len(possiblebonds)):
for j in range(len(possiblebonds[i])):
if possiblebonds[i][j][1]==particlenum:
del possiblebonds[i][j]
break #go to next row of possiblebonds
return possiblebonds
def bondtoparticle(self,particle,atomid,newid,newcharge):
"""Bonds molecule to particle. Particle is a particlesurface object.
Moves the molecule's atoms bonded to the particle to the particle's position.
Alters the atomtype of the molecule's atoms bonded to the particle to newid.
Alters the charge of the molecule's atoms bonded to the particle to newcharge
Because bonds have formed between the molecule's atoms and the particle's atoms,
atoms with atomid on the molecule need to be removed otherwise the molecule's atoms will have to many bonds.
self.deleteatoms will take care of deleting the atoms atomid and
atoms down the polymer chain in the direction away from the molecule/particle bond.
Now remove the bonded particle atoms from the particle surface becaused the bonded molecule atoms
have replaced those particle atoms and their bonds with the rest of the particle.
Newid must be a string. Atomid can now be a list or an integer.
The list is a list of atom's id values and the single integer is atom's atomtype"""
#moves the molecule's atoms bonded to the particle to the particle's position
#need to do this step first before the atom id's and row indexes get out of sync
#which will occur after atoms get deleted.
print 'modifying the bonded molecules atom information'
for i in range(len(self.bondinginformation)):
#patom=particle.getsurfatom(self.bondinginformation[i][1])
#if self.atomtype=='molecular':#3-5->x,y,z[molecular]
# for j in range(3,6):
# self.modifyatom(self.bondinginformation[i][0]+1,j,patom[j])#uses the atomid here
#elif self.atomtype=='full':#4-6->x,y,z[full]
# for j in range(4,7):
# self.modifyatom(self.bondinginformation[i][0]+1,j,patom[j])#uses the atomid here
#alters the atomtype to newid of the molecule's atoms bonded to the particle.
self.modifyatom(self.bondinginformation[i][0]+1,2,newid) #uses the atomid here
if self.atomtype=='full':
# Alters the charge of the molecule's atoms bonded to the particle to newcharge
self.modifyatom(self.bondinginformation[i][0]+1,3,newcharge)
#This is a seperate loop so atom id's and row indexes for previous steps wont get out of sync
#create atomnumbers to begin deletion process.
atomnumbers=[]
for i in range(len(self.bondinginformation)):
atomnumbers.append(self.bondinginformation[i][0]+1)#using actual atomnumbers rather than the row index
#Call algorithm to find all atoms bonded to atomnumbers in the direction of atomid.
#Than delete those atoms and all molecule structures which contain those atoms.
self.deleteatoms(atomnumbers,atomid)
print 'begining deletion process of the surface atoms for which the molecule atoms have replaced'
#Goes through the bondinginformation and superficially removes the surfaceatom
for i in range(len(self.bondinginformation)):
particle.removesurfatom(self.bondinginformation[i][1]) #uses the row number
#Allows the particle extract method used outside this class to remove this atom.
def createxyz(self,file,data,routine='mass', values=None):
"""Two possible routines one to use the masses from data and the other to use the atom type and values supplied by the user.
The mass version is assessed by setting the routine to 'mass' which is the default method.
The other version is assessed by setting the routine to 'atomtype'.
The other version takes values which is a list containing the value the user wants to assign those atomtypes to.
The atomtypes of the values in the list will start at 1 even if no atoms in molecule use 1.
This makes it easier to find the atomtype and assign the value from the list
All atom data is assumed to have image flags in the data."""
f=open(file,'w')
f.write('{0}\n'.format(len(self.atoms)))
f.write('atoms\n')
if routine=='mass':
for line in self.atoms:
type=int(line[2])-1
mass=data.masses[type][1]
if mass=='12.0107': elementnum=6
elif mass=='15.9994': elementnum=8
elif mass=='26.9815':elementnum=13
else:
print 'no matching mass value. The method will exit'
return
l=len(line)-1
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[l-5],line[l-4],line[l-3]))
f.close()
elif routine=='atomtype':
for line in self.atoms:
type=int(line[2])-1
elementnum=values[type]
l=len(line)-1
f.write('{0} {1} {2} {3}\n'.format(elementnum,line[l-5],line[l-4],line[l-3]))
f.close()