All-- I'm a new user of sympy, and have been really impressed by how easy it is to get started. :-) However, I recently came across a problem that's been causing sympy to hang, and am not sure whether (a) it is an intractable problem that sympy simply can't solve, (b) there is some hint I could give sympy which would let it proceed, or (c) I just need to let it run for a week. Specifically, I'm trying to compute the surface area of a quartic triangle Bezier patch. The way this works is that you have fifteen control points (X, a 15 x 3 matrix) and a corresponding fifteen basis functions (b, a vector length fifteen, in terms of parameters s and t). The position for a given s and t is given by X^T b. I'm trying to solve for a general patch, X is a matrix of yet unknown constants. The surface area can be found by evaluating a pretty intense double integral [1], which is what's giving sympy trouble.
I've attached the script I'm using--I'd be infinitely grateful if someone with more experience could offer any advice! Best, and thanks to everyone who has contributed to this invaluable software! --Davis P.S. I've added a guard to the beginning of the script because when I ran this with 0.7.4 (default for Ubuntu 14.04 when installing with apt-get) it resulted in unbounded memory use and crashed my machine--happily, updating to the development branch fixed this. [1] https://en.wikipedia.org/wiki/Parametric_surface#Surface_area -- You received this message because you are subscribed to the Google Groups "sympy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sympy+unsubscr...@googlegroups.com. To post to this group, send email to sympy@googlegroups.com. Visit this group at https://groups.google.com/group/sympy. To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/1488db59-35b6-4fe9-a602-501f304e82b6%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
""" author: Davis Vigneault """ import sympy as sp import copy import pickle import os #x, y = sp.symbols('x y') r, s, t = sp.symbols('r s t') r1, r2, r3, r4 = sp.symbols('r1 r2 r3 r4') s1, s2, s3, s4 = sp.symbols('s1 s2 s3 s4') t1, t2, t3, t4 = sp.symbols('t1 t2 t3 t4') def expand_powers(expr): rep_r = [(r1,r**1),(r2,r**2),(r3,r**3),(r4,r**4)] rep_s = [(s1,s**1),(s2,s**2),(s3,s**3),(s4,s**4)] rep_t = [(t1,t**1),(t2,t**2),(t3,t**3),(t4,t**4)] expr = expr.subs(rep_r) expr = expr.subs(rep_s) expr = expr.subs(rep_t) return expr def basis_functions(): position_basis = sp.Matrix([s4, # p0 t4, # p1 r4, # p2 4*r1*s3, # p0- 4*t1*s3, # p0+ 4*s1*t3, # p1- 4*r1*t3, # p1+ 4*t1*r3, # p2- 4*s1*r3, # p2+ 6*s2*t2, # p01 6*t2*r2, # p12 6*r2*s2, # p20 12*s2*t1*r1, # p0m 12*s1*t2*r1, # p0m 12*s1*t1*r2]) # p0m position_basis = expand_powers(position_basis) return position_basis def bezier_surfacearea(): """ https://en.wikipedia.org/wiki/Parametric_surface#Surface_area """ # Create a directory where the output will be saved. if not os.path.exists("data/"): os.makedirs("data/") # Vector of basis functions, length 15, in terms of r, s, and t. bezier_weights = basis_functions() # The parametric region is the unit triangle: # 0 <= t <= 1 # 0 <= s <= 1 - t # 0 <= r <= 1 - s - t # R can be eliminated bezier_weights = bezier_weights.subs( { r : 1 - s - t } ) print "Bezier Basis:" sp.pprint(bezier_weights) # Differentiate w.r.t. the remaining parameters, s and t. bezier_basis_s = copy.deepcopy(bezier_weights).diff(s) print "Partial derivative with respect to s:" sp.pprint(bezier_basis_s) bezier_basis_t = copy.deepcopy(bezier_weights).diff(t) print "Partial derivative with respect to t:" sp.pprint(bezier_basis_t) # The position function is defined in terms of 15 control points. X = map(lambda i: sp.Symbol('X_({0},{1})'.format(i / 3, i % 3)), xrange(45)) X = sp.Matrix(15,3,X) print "Control point matrix:" sp.pprint(X) Rs = sp.Matrix(X.dot(bezier_basis_s)) print "X^T * bs:" sp.pprint(Rs) Rt = sp.Matrix(X.dot(bezier_basis_t)) print "X^T * bt:" sp.pprint(Rt) print "Calculating the norm of the cross product..." cp = Rs.cross(Rt).norm() with open("data/cross_product.txt", "w") as output_file: pickle.dump(cp, output_file) print "Computing first integral..." int_1 = cp.integrate((s, 0, (1 - t))) with open("data/inner_integral.txt", "w") as output_file: pickle.dump(int_1, output_file) print "Computing second integral..." int_2 = int_1.integrate((t, 0, 1)) with open("data/outer_integral.txt", "w") as output_file: pickle.dump(int_2, output_file) def main(): if (int(sp.__version__[0]) < 1): print 'ERROR:' print """Running this script using sympy version 0.7.4 (the version you get from apt-get on Ubuntu 14.04) resulted in unbounded memory usage and a system crash. Updating to the development branch (1.0.1-dev) fixed this issue, though I don\'t know which specific patch has the fix. Please be aware of this if you decide to uncomment this block.""" return bezier_surfacearea() if __name__ == '__main__': main()