diff --git a/theory/Multipoles/multipoles.py b/theory/Multipoles/multipoles.py
new file mode 100644
index 0000000000000000000000000000000000000000..e4009ee2c0aee4973d2484212abbac25d6fa796e
--- /dev/null
+++ b/theory/Multipoles/multipoles.py
@@ -0,0 +1,179 @@
+import numpy as np
+import sys
+
+def factorial(x):
+    if x == 0:
+        return 1
+    else:
+        return x * factorial(x-1)
+
+SUFFIXES = {1: 'st', 2: 'nd', 3: 'rd'}
+def ordinal(num):
+    suffix = SUFFIXES.get(num % 10, 'th')
+    return str(num) + suffix
+
+# Get the order
+order = int(sys.argv[1])
+
+print "-------------------------------------------------"
+print "Generating code for multipoles of order", order, "(only)."
+print "-------------------------------------------------\n"
+
+print "-------------------------------------------------"
+print "Multipole structure:"
+print "-------------------------------------------------\n"
+
+if order > 0:
+    print "#if SELF_GRAVITY_MULTIPOLE_ORDER > %d\n"%(order-1)
+
+print "/* %s order terms */"%ordinal(order)
+    
+# Create all the terms relevent for this order
+for i in range(order+1):
+    for j in range(order+1):
+        for k in range(order+1):
+            if i + j + k == order:
+                print "float M_%d%d%d;"%(i,j,k)
+
+if order > 0:
+    print "#endif"
+
+print ""
+print "-------------------------------------------------"
+
+print "Field tensor structure:"
+print "-------------------------------------------------\n"
+
+if order > 0:
+    print "#if SELF_GRAVITY_MULTIPOLE_ORDER > %d\n"%(order-1)
+
+print "/* %s order terms */"%ordinal(order)
+    
+# Create all the terms relevent for this order
+for i in range(order+1):
+    for j in range(order+1):
+        for k in range(order+1):
+            if i + j + k == order:
+                print "float F_%d%d%d;"%(i,j,k)
+if order > 0:
+    print "#endif"
+
+print ""
+print "-------------------------------------------------"
+
+print "gravity_field_tensors_add():"
+print "-------------------------------------------------\n"
+
+if order > 0:
+    print "#if SELF_GRAVITY_MULTIPOLE_ORDER > %d"%(order-1)
+
+print "/* %s order terms */"%ordinal(order)
+    
+# Create all the terms relevent for this order
+for i in range(order+1):
+    for j in range(order+1):
+        for k in range(order+1):
+            if i + j + k == order:
+                print "la->F_%d%d%d += lb->F_%d%d%d;"%(i,j,k,i,j,k)
+if order > 0:
+    print "#endif"
+
+print ""
+print "-------------------------------------------------"
+
+print "gravity_multipole_add():"
+print "-------------------------------------------------\n"
+
+if order > 0:
+    print "#if SELF_GRAVITY_MULTIPOLE_ORDER > %d"%(order-1)
+
+print "/* %s order terms */"%ordinal(order)
+    
+# Create all the terms relevent for this order
+for i in range(order+1):
+    for j in range(order+1):
+        for k in range(order+1):
+            if i + j + k == order:
+                print "ma->M_%d%d%d += mb->M_%d%d%d;"%(i,j,k,i,j,k)
+if order > 0:
+    print "#endif"
+
+print ""
+print "-------------------------------------------------"
+
+print "gravity_P2M(): (loop)"
+print "-------------------------------------------------\n"
+
+if order > 0:
+    print "#if SELF_GRAVITY_MULTIPOLE_ORDER > %d"%(order-1)
+
+print "/* %s order terms */"%ordinal(order)
+    
+# Create all the terms relevent for this order
+for i in range(order+1):
+    for j in range(order+1):
+        for k in range(order+1):
+            if i + j + k == order:
+                if order % 2 == 0:
+                    print "M_%d%d%d += m * X_%d%d%d(dx);"%(i,j,k,i,j,k)
+                else:
+                    print "M_%d%d%d += -m * X_%d%d%d(dx);"%(i,j,k,i,j,k)
+if order > 0:
+    print "#endif"
+
+print ""
+print "-------------------------------------------------"
+    
+print "gravity_P2M(): (storing)"
+print "-------------------------------------------------\n"
+
+if order > 0:
+    print "#if SELF_GRAVITY_MULTIPOLE_ORDER > %d"%(order-1)
+
+print "/* %s order terms */"%ordinal(order)
+    
+# Create all the terms relevent for this order
+for i in range(order+1):
+    for j in range(order+1):
+        for k in range(order+1):
+            if i + j + k == order:
+                print "m->m_pole.M_%d%d%d = M_%d%d%d;"%(i,j,k,i,j,k)
+if order > 0:
+    print "#endif"
+
+
+print ""
+print "-------------------------------------------------"
+
+print "gravity_M2M():"
+print "-------------------------------------------------\n"
+
+if order > 0:
+    print "#if SELF_GRAVITY_MULTIPOLE_ORDER > %d"%(order-1)
+
+print "/* Shift %s order terms */"%ordinal(order)
+    
+# Create all the terms relevent for this order
+for i in range(order+1):
+    for j in range(order+1):
+        for k in range(order+1):
+            if i + j + k == order:
+                print "m_a->.M_%d%d%d = m_b->M_%d%d%d"%(i,j,k,i,j,k),
+
+                for ii in range(order+1):
+                    for jj in range(order+1):
+                        for kk in range(order+1):
+
+                            if not(ii == 0 and jj == 0 and kk == 0):
+                                for iii in range(order+1):
+                                    for jjj in range(order+1):
+                                        for kkk in range(order+1):
+                                            if ii+iii == i and jj + jjj == j and kk+kkk == k:
+                                                print "+ X_%d%d%d(dx) * m_b->M_%d%d%d"%(ii, jj, kk, iii, jjj, kkk),
+
+                                        
+                print ";"
+if order > 0:
+    print "#endif"
+
+