Skip to content

Instantly share code, notes, and snippets.

@shoke
Created May 16, 2011 07:20
Show Gist options
  • Save shoke/974032 to your computer and use it in GitHub Desktop.
Save shoke/974032 to your computer and use it in GitHub Desktop.
Graphene
import networkx as nx
import matplotlib as mat
import matplotlib.pyplot as plt
import numpy as np
# Colors each node in the given graph based on the data
# Set provided
def color_graph(graph, d, cmap):
col_graph = nx.Graph()
#normalize the data and create an array of colors that will
#correspond to the nodes in the graph
data = (normalize(d))
color_array = []
for j in range(len(data)):
color = cmap(data[j])
color_array.append( color )
i = 0
# add the color to each node
for node in graph.nodes():
red = int(255*color_array[i][0])
blu = int(255*color_array[i][1])
gre = int(255*color_array[i][2])
alp = color_array[i][3]
i = i + 1
col_graph.add_node(node,{'viz':{'color':dict(r=red,b=blu,g=gre,a=alp)}})
col_graph.add_edges_from(graph.edges())
return col_graph
# Normalizes the given data between 0 and 1
def normalize(data):
d = []
min = float(np.min(data))
max = float(np.max(data))
data_range = max - min
for j in range(len(data)):
d.append( ( float(data[j]) - min) / data_range )
return d
# Utilizes the networkx draw_networkx function
# Useful for small graphs
def graphene_graph(g, data, cmap = plt.cm.Blues):
min = float(np.min(data))
max = float(np.max(data))
nx.draw_networkx(g, cmap = cmap, vmin = min, vmax = max, node_color = data)
plt.show()
import networkx as nx
import matplotlib as mat
import matplotlib.pyplot as plt
import colorgraph
# Builds a graphene sheet with the given number of rows and columns.
# If wrap is set to true it will roll it up
def build_graph(rows, columns, wrap):
g = nx.Graph()
# creates the first complete hexagon
for i in range(6):
if (i+1) > 1:
g.add_edge(i+1,i)
g.add_edge(6,1)
# top of the first hexagon, start and end of the next hexagon
start = 4
end = 5
numNodes = 6
# if the number of hexagons in the row is greater than 1
if rows > 1:
for j in range(rows-1):
s = start
# 2 nodes already placed, adds the next 4
for addnodes in range(4):
g.add_edge(s, numNodes+1)
numNodes += 1
s = numNodes
g.add_edge(numNodes, end)
start += 4
end += 4
evenColumn = True
secondColumn = True
connection = 1
# startingNode is the node the NEXT column will start at
# (aka the bottom of the one being drawn)
startingNode = numNodes + 1
# start is your current postion
start = startingNode
# if there is more than one column
if columns > 1:
for k in range(columns-1):
# even vs. odd columns start and end differently
if evenColumn:
# the connection to the last finished column
# the first hexagon in each new column has one extra node
connection += 2
if not(k == (columns-2)):
g.add_edge(start, start+1)
start += 1
numNodes +=1
g.add_edge(start, start+1)
g.add_edge(start, connection)
numNodes += 1
for l in range(rows -1):
# the second column is a special case
if secondColumn:
connection += 4
else:
connection += 2
start += 1
g.add_edge(start-1, start)
g.add_edge(start, start+1)
start += 1
g.add_edge(start, connection)
numNodes += 2
# finish column
if not(k == (columns-2)):
g.add_edge(numNodes , numNodes +1)
numNodes +=1
evenColumn = False
secondColumn = False
connection = startingNode
startingNode = numNodes
start = numNodes +1
else:
g.add_edge(start, connection)
g.add_edge(start, start+1)
start += 1
g.add_edge(start, start+1)
start += 1
connection += 2
g.add_edge(start, connection)
numNodes += 3
for l in range(rows -1):
connection += 2
g.add_edge(start+1, start)
start += 1
g.add_edge(start, start+1)
start += 1
g.add_edge(start, connection)
numNodes += 2
# finish column
start += 1
evenColumn = True
connection = startingNode
startingNode = start
# are we rolling the sheet?
if wrap and (rows > 0):
g.remove_node( 2 + (rows * 4) - 1 )
g.add_edge( 2 + (rows * 4) , 1 )
g.remove_node( 2 + (rows * 4) - 2 )
g.add_edge( 2 + (rows * 4) - 3, 2 )
start = 3 + (rows * 4)
for k in range(columns-1):
end = 2 * rows + start
g.remove_node( end )
g.add_edge( end - 1, start )
start = end + 1
return g
def build_and_color(rows,columns,wrap,data,cmap = plt.cm.Blues, filename = "test.gexf"):
g = build_graph(rows,columns,wrap)
g = colorgraph.color_graph(g,data,cmap)
nx.write_gexf(g,filename)
# Builds a graphene sheet with the given number of rows and columns.
# The sheet has a defected column running through the optionally passed
# arg. Otherwise it defaults to the center.
def defected_graphene_graph(rows, columns, defect = 0):
g = nx.Graph()
index = 0;
if( columns <= 2 ):
print "Must have more than two columns."
return g
if( rows < 2 ):
print "Must have more than 1 row."
return g
if defect[index] == 1:
print "Defect wire cannot be on edge column."
if defect[index] == columns:
print "Defect wire cannot be on edge column."
if (defect[index] == 0) :
defect[index] = int(columns/2) + 1
# creates the first complete hexagon
for i in range(6):
if (i+1) > 1:
g.add_edge(i+1,i)
g.add_edge(6,1)
# top of the first hexagon, start and end of the next hexagon
start = 4
end = 5
numNodes = 6
# if the number of hexagons in the row is greater than 1
if rows > 1:
for j in range(rows-1):
s = start
# 2 nodes already placed, adds the next 4
for addnodes in range(4):
g.add_edge(s, numNodes+1)
s = numNodes + 1
numNodes += 1
g.add_edge(numNodes, end)
start += 4
end += 4
evenColumn = True
secondColumn = True
connection = 1
# startingNode is the node the NEXT column will start at
# (aka the bottom of the one being drawn)
startingNode = numNodes + 1
# start is your current postion
start = startingNode
afterDefect = False
after2 = False
# if there is more than one column
if columns > 1:
for k in range(columns-1):
if( k+2 == defect[index] ):
if evenColumn:
connection += 2
g.add_edge(connection, start)
g.add_edge(start, start+1)
g.add_edge(start+1, start+2)
g.add_edge(start+1, start+2)
g.add_edge(start+2, start+3)
g.add_edge(start+3, start+4)
numNodes += 5
# the second column is a special case
if secondColumn:
connection += 4
else:
connection += 2
g.add_edge(connection, start+4)
start += 4
evenRow = True
for l in range(rows -2):
if evenRow:
# the second column is a special case
if secondColumn:
connection += 4
elif afterDefect:
connection += 4
else:
connection += 2
g.add_edge(start, start+1)
g.add_edge(start+1, connection)
start = start -1
g.add_edge(start, start+3)
g.add_edge(start+3, start + 4)
g.add_edge(start+2, start + 4)
start += 4
numNodes += 3
evenRow = False
else:
# the second column is a special case
if secondColumn:
connection += 4
else:
connection += 2
g.add_edge(start, start+1)
g.add_edge(start+2, start+1)
g.add_edge(start+2, start+3)
g.add_edge(connection, start+3)
numNodes += 3
start += 3
evenRow = True
if not evenColumn:
if evenRow:
# the second column is a special case
if secondColumn:
connection += 4
else:
connection += 2
g.add_edge(start, start+1)
if not afterDefect:
g.add_edge(start+1, connection)
start = start -1
g.add_edge(start, start+3)
g.add_edge(start+3, start + 4)
g.add_edge(start+2, start + 4)
start += 2
if afterDefect:
g.add_edge(start, start+3)
g.add_edge(start+3, start+4)
g.add_edge(start+4, connection-2)
start += 2
numNodes += 5
evenRow = False
else:
connection += 2
g.add_edge(start, start+1)
start += 1
g.add_edge(start, start+1)
start += 1
g.add_edge(start, start+1)
start += 1
g.add_edge(start, connection)
numNodes += 3
connection = startingNode + 1
start = numNodes +1
evenColumn = not evenColumn
startingNode = numNodes
secondColumn = False
afterDefect = True
if not(index == (len(defect)-1)):
index = index + 1
# even vs. odd columns start and end differently
elif evenColumn:
# the connection to the last finished column
# the first hexagon in each new column has one extra node
connection += 2
if not(k == (columns-2)):
g.add_edge(start, start+1)
start += 1
numNodes +=1
g.add_edge(start, start+1)
if afterDefect:
#connection += 1
evenRow = True
g.add_edge(start, connection)
numNodes += 1
for l in range(rows -1):
# the second column is a special case
if secondColumn:
connection += 4
elif afterDefect:
if evenRow:
connection += 4
evenRow = False
else:
connection += 2
evenRow = True
else:
connection += 2
start += 1
g.add_edge(start-1, start)
g.add_edge(start, start+1)
start += 1
g.add_edge(start, connection)
numNodes += 2
# finish column
if not(k == (columns-2)):
g.add_edge(numNodes , numNodes +1)
numNodes +=1
evenColumn = False
secondColumn = False
connection = startingNode
if afterDefect:
connection += 1
elif after2:
g.add_edge(numNodes, numNodes + 1)
numNodes += 1
startingNode = numNodes
start = numNodes +1
afterDefect = False
else:
g.add_edge(start, connection)
g.add_edge(start, start+1)
start += 1
g.add_edge(start, start+1)
start += 1
if afterDefect:
g.add_edge(start, start+1)
start += 1
connection += 1
evenRow = True
else:
connection += 2
g.add_edge(start, connection)
numNodes += 3
for l in range(rows -1):
if afterDefect:
if evenRow:
connection += 4
evenRow = False
else:
connection += 2
evenRow = True
else:
connection += 2
g.add_edge(start+1, start)
start += 1
g.add_edge(start, start+1)
start += 1
if( l == (rows-2) ):
if afterDefect:
g.add_edge(start +1, start)
if evenRow:
g.add_edge(start +1, connection-1)
else:
g.add_edge(start +1, connection-3)
numNodes += 3
else:
g.add_edge(start, connection)
numNodes += 2
else:
g.add_edge(start, connection)
numNodes += 2
# finish column
start += 1
evenColumn = True
if after2:
after2 = False
if afterDefect:
startingNode += 1
after2 = True
start += 1
connection = startingNode
startingNode = start
afterDefect = False
return g
import networkx as nx
import random
# Adds the number of defects specified to the graph. Removes the nodes randomly
# and all adjacent edges
def add_defects(graph, number):
# do we have enough nodes?
if (number >= len(graph.nodes()) ):
print "The number of defects must be less than the size of the graph"
return graph
# randomly generate nodes to pull
defects = random.sample(graph.nodes(), number)
for i in range(len(defects)):
graph.remove_node(defects[i])
return graph
def stonewales_defect(graph, node):
neighbors = graph.neighbors(node)
new_graph = graph
node2 = 0
if neighbors[0] < node:
if neighbors[1] < node:
node2 = node-1
elif neighbors[2] < node:
node2 = node-1
else:
node2 = node
node = node+1
elif neighbors[0] > node:
if neighbors[1] > node:
node2 = node
node = node+1
elif neighbors[2] > node:
node2 = node
node = node+1
else:
node2 = node-1
if(len(graph.neighbors(node)) < 3):
print "Bad node"
return graph
if(len(graph.neighbors(node2)) < 3):
print "Bad node"
return graph
new_graph.remove_edge(node, node+1)
new_graph.remove_edge(node, node-1)
new_graph.add_edge(node,node-2)
new_graph.remove_edge(node2, node2-1)
new_graph.add_edge(node2,node2+2)
new_graph.add_edge(node,node2)
return new_graph
# Builds a complete two-node graph
def build_two_node():
return nx.complete_graph(2)
# Builds a complete three-node graph
def build_three_node():
return nx.complete_graph(3)
# Builds a complete four-node graph
def build_four_node():
return nx.complete_graph(4)
import networkx as nx
def get_hamiltonian(g):
return -0.5 * nx.laplacian(g)
@ellisonbg
Copy link

OK, great start. As a next step, let's put the main part of the code in a python function that takes the input parameters (rows, columns) and returns a networkx graph object. After that, I think we want to begin to work on characterizing the sheet using the lattice unit vectors a_1 and a_2. These provide a very powerful and exact way of describing any sheet of graphene (or nanotube). A good starting point for learning about this is the Wikipedia page on Carbon Nanotubes: http://en.wikipedia.org/wiki/Carbon_nanotube

I will have research office hours this Wed and we can talk more about this then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment