def slope(self): """ Returns a Singularity Function expression which represents the slope the elastic curve of the Beam object. Examples ======== There is a beam of length 30 meters. A moment of magnitude 120 Nm is applied in the clockwise direction at the end of the beam. A pointload of magnitude 8 N is applied from the top of the beam at the starting point. There are two simple supports below the beam. One at the end and another one at a distance of 10 meters from the start. The deflection is restricted at both the supports. Using the sign convention of upward forces and clockwise moment being positive. >>> from sympy.physics.continuum_mechanics.beam import Beam >>> from sympy import symbols >>> E, I = symbols('E, I') >>> R1, R2 = symbols('R1, R2') >>> b = Beam(30, E, I) >>> b.apply_load(-8, 0, -1) >>> b.apply_load(R1, 10, -1) >>> b.apply_load(R2, 30, -1) >>> b.apply_load(120, 30, -2) >>> b.bc_deflection = [(10, 0), (30, 0)] >>> b.solve_for_reaction_loads(R1, R2) >>> b.slope() (-4*SingularityFunction(x, 0, 2) + 3*SingularityFunction(x, 10, 2) + 120*SingularityFunction(x, 30, 1) + SingularityFunction(x, 30, 2) + 4000/3)/(E*I) """ x = self.variable E = self.elastic_modulus I = self.second_moment if not self._boundary_conditions['slope']: return diff(self.deflection(), x) C3 = Symbol('C3') slope_curve = integrate(self.bending_moment(), x) + C3 bc_eqs = [] for position, value in self._boundary_conditions['slope']: eqs = slope_curve.subs(x, position) - value bc_eqs.append(eqs) constants = list(linsolve(bc_eqs, C3)) slope_curve = slope_curve.subs({C3: constants[0][0]}) return S(1)/(E*I)*slope_curve
def slope(self): """ Returns a Singularity Function expression which represents the slope the elastic curve of the Beam object. Examples ======== There is a beam of length 30 meters. A moment of magnitude 120 Nm is applied in the clockwise direction at the end of the beam. A pointload of magnitude 8 N is applied from the top of the beam at the starting point. There are two simple supports below the beam. One at the end and another one at a distance of 10 meters from the start. The deflection is restricted at both the supports. Using the sign convention of upward forces and clockwise moment being positive. >>> from sympy.physics.continuum_mechanics.beam import Beam >>> from sympy import symbols >>> E, I = symbols('E, I') >>> R1, R2 = symbols('R1, R2') >>> b = Beam(30, E, I) >>> b.apply_load(-8, 0, -1) >>> b.apply_load(R1, 10, -1) >>> b.apply_load(R2, 30, -1) >>> b.apply_load(120, 30, -2) >>> b.bc_deflection = [(10, 0), (30, 0)] >>> b.solve_for_reaction_loads(R1, R2) >>> b.slope() (-4*SingularityFunction(x, 0, 2) + 3*SingularityFunction(x, 10, 2) + 120*SingularityFunction(x, 30, 1) + SingularityFunction(x, 30, 2) + 4000/3)/(E*I) """ x = self.variable E = self.elastic_modulus I = self.second_moment if not self._boundary_conditions['slope']: return diff(self.deflection(), x) C3 = Symbol('C3') slope_curve = integrate(self.bending_moment(), x) + C3 bc_eqs = [] for position, value in self._boundary_conditions['slope']: eqs = slope_curve.subs(x, position) - value bc_eqs.append(eqs) constants = list(linsolve(bc_eqs, C3)) slope_curve = slope_curve.subs({C3: constants[0][0]}) return S(1) / (E * I) * slope_curve
def solve_for_reaction_loads(self, *reactions): """ Solves for the reaction forces. Examples ======== There is a beam of length 30 meters. A moment of magnitude 120 Nm is applied in the clockwise direction at the end of the beam. A pointload of magnitude 8 N is applied from the top of the beam at the starting point. There are two simple supports below the beam. One at the end and another one at a distance of 10 meters from the start. The deflection is restricted at both the supports. Using the sign convention of upward forces and clockwise moment being positive. >>> from sympy.physics.continuum_mechanics.beam import Beam >>> from sympy import symbols, linsolve, limit >>> E, I = symbols('E, I') >>> R1, R2 = symbols('R1, R2') >>> b = Beam(30, E, I) >>> b.apply_load(-8, 0, -1) >>> b.apply_load(R1, 10, -1) # Reaction force at x = 10 >>> b.apply_load(R2, 30, -1) # Reaction force at x = 30 >>> b.apply_load(120, 30, -2) >>> b.bc_deflection = [(10, 0), (30, 0)] >>> b.load R1*SingularityFunction(x, 10, -1) + R2*SingularityFunction(x, 30, -1) - 8*SingularityFunction(x, 0, -1) + 120*SingularityFunction(x, 30, -2) >>> b.solve_for_reaction_loads(R1, R2) >>> b.reaction_loads {R1: 6, R2: 2} >>> b.load -8*SingularityFunction(x, 0, -1) + 6*SingularityFunction(x, 10, -1) + 120*SingularityFunction(x, 30, -2) + 2*SingularityFunction(x, 30, -1) """ if self._composite_type == "hinge": return self._solve_hinge_beams(*reactions) x = self.variable l = self.length shear_curve = limit(self.shear_force(), x, l) moment_curve = limit(self.bending_moment(), x, l) reaction_values = linsolve([shear_curve, moment_curve], reactions).args self._reaction_loads = dict(zip(reactions, reaction_values[0])) self._load = self._load.subs(self._reaction_loads)
def deflection(self): """ Returns a Singularity Function expression which represents the elastic curve or deflection of the Beam object. Examples ======== There is a beam of length 30 meters. A moment of magnitude 120 Nm is applied in the clockwise direction at the end of the beam. A pointload of magnitude 8 N is applied from the top of the beam at the starting point. There are two simple supports below the beam. One at the end and another one at a distance of 10 meters from the start. The deflection is restricted at both the supports. Using the sign convention of upward forces and clockwise moment being positive. >>> from sympy.physics.continuum_mechanics.beam import Beam >>> from sympy import symbols >>> E, I = symbols('E, I') >>> R1, R2 = symbols('R1, R2') >>> b = Beam(30, E, I) >>> b.apply_load(-8, 0, -1) >>> b.apply_load(R1, 10, -1) >>> b.apply_load(R2, 30, -1) >>> b.apply_load(120, 30, -2) >>> b.bc_deflection = [(10, 0), (30, 0)] >>> b.solve_for_reaction_loads(R1, R2) >>> b.deflection() (4000*x/3 - 4*SingularityFunction(x, 0, 3)/3 + SingularityFunction(x, 10, 3) + 60*SingularityFunction(x, 30, 2) + SingularityFunction(x, 30, 3)/3 - 12000)/(E*I) """ x = self.variable E = self.elastic_modulus I = self.second_moment if self._composite_type == "hinge": return self._hinge_beam_deflection if not self._boundary_conditions['deflection'] and not self._boundary_conditions['slope']: if self._composite_type == "fixed": args = I.args conditions = [] prev_def = 0 prev_end = 0 for i in range(len(args)): if i != 0: prev_end = args[i-1][1].args[1] deflection_value = integrate(self.slope().args[i][0], (x, prev_end, x)) conditions.append(((prev_def + deflection_value), args[i][1])) prev_def = deflection_value.subs(x, args[i][1].args[1]) return Piecewise(*conditions) return S(1)/(E*I)*integrate(integrate(self.bending_moment(), x), x) elif not self._boundary_conditions['deflection']: return integrate(self.slope(), x) elif not self._boundary_conditions['slope'] and self._boundary_conditions['deflection']: if self._composite_type == "fixed": args = I.args conditions = [] prev_def = 0 prev_end = 0 for i in range(len(args)): if i != 0: prev_end = args[i-1][1].args[1] deflection_value = integrate(self.slope().args[i][0], (x, prev_end, x)) conditions.append(((prev_def + deflection_value), args[i][1])) prev_def = deflection_value.subs(x, args[i][1].args[1]) return Piecewise(*conditions) C3 = Symbol('C3') C4 = Symbol('C4') slope_curve = integrate(self.bending_moment(), x) + C3 deflection_curve = integrate(slope_curve, x) + C4 bc_eqs = [] for position, value in self._boundary_conditions['deflection']: eqs = deflection_curve.subs(x, position) - value bc_eqs.append(eqs) constants = list(linsolve(bc_eqs, (C3, C4))) deflection_curve = deflection_curve.subs({C3: constants[0][0], C4: constants[0][1]}) return S(1)/(E*I)*deflection_curve if self._composite_type == "fixed": args = I.args conditions = [] prev_def = 0 prev_end = 0 for i in range(len(args)): if i != 0: prev_end = args[i-1][1].args[1] deflection_value = integrate(self.slope().args[i][0], (x, prev_end, x)) conditions.append(((prev_def + deflection_value), args[i][1])) prev_def = deflection_value.subs(x, args[i][1].args[1]) return Piecewise(*conditions) C4 = Symbol('C4') deflection_curve = integrate((E*I)*self.slope(), x) + C4 bc_eqs = [] for position, value in self._boundary_conditions['deflection']: eqs = deflection_curve.subs(x, position) - value bc_eqs.append(eqs) constants = list(linsolve(bc_eqs, C4)) deflection_curve = deflection_curve.subs({C4: constants[0][0]}) return S(1)/(E*I)*deflection_curve
def solve_for_reaction_loads(self, *reactions): """ Solves for the reaction forces. Examples ======== There is a beam of length 30 meters. A moment of magnitude 120 Nm is applied in the clockwise direction at the end of the beam. A pointload of magnitude 8 N is applied from the top of the beam at the starting point. There are two simple supports below the beam. One at the end and another one at a distance of 10 meters from the start. The deflection is restricted at both the supports. Using the sign convention of upward forces and clockwise moment being positive. >>> from sympy.physics.continuum_mechanics.beam import Beam >>> from sympy import symbols, linsolve, limit >>> E, I = symbols('E, I') >>> R1, R2 = symbols('R1, R2') >>> b = Beam(30, E, I) >>> b.apply_load(-8, 0, -1) >>> b.apply_load(R1, 10, -1) # Reaction force at x = 10 >>> b.apply_load(R2, 30, -1) # Reaction force at x = 30 >>> b.apply_load(120, 30, -2) >>> b.bc_deflection = [(10, 0), (30, 0)] >>> b.load R1*SingularityFunction(x, 10, -1) + R2*SingularityFunction(x, 30, -1) - 8*SingularityFunction(x, 0, -1) + 120*SingularityFunction(x, 30, -2) >>> b.solve_for_reaction_loads(R1, R2) >>> b.reaction_loads {R1: 6, R2: 2} >>> b.load -8*SingularityFunction(x, 0, -1) + 6*SingularityFunction(x, 10, -1) + 120*SingularityFunction(x, 30, -2) + 2*SingularityFunction(x, 30, -1) """ if self._composite_type == "hinge": return self._solve_hinge_beams(*reactions) x = self.variable l = self.length C3 = Symbol('C3') C4 = Symbol('C4') shear_curve = limit(self.shear_force(), x, l) moment_curve = limit(self.bending_moment(), x, l) slope_eqs = [] deflection_eqs = [] slope_curve = integrate(self.bending_moment(), x) + C3 for position, value in self._boundary_conditions['slope']: eqs = slope_curve.subs(x, position) - value slope_eqs.append(eqs) deflection_curve = integrate(slope_curve, x) + C4 for position, value in self._boundary_conditions['deflection']: eqs = deflection_curve.subs(x, position) - value deflection_eqs.append(eqs) solution = list((linsolve([shear_curve, moment_curve] + slope_eqs + deflection_eqs, (C3, C4) + reactions).args)[0]) solution = solution[2:] self._reaction_loads = dict(zip(reactions, solution)) self._load = self._load.subs(self._reaction_loads)
def _solve_hinge_beams(self, *reactions): """Method to find integration constants and reactional variables in a composite beam connected via hinge. This method resolves the composite Beam into its sub-beams and then equations of shear force, bending moment, slope and deflection are evaluated for both of them separately. These equations are then solved for unknown reactions and integration constants using the boundary conditions applied on the Beam. Equal deflection of both sub-beams at the hinge joint gives us another equation to solve the system. Examples ======== A combined beam, with constant fkexural rigidity E*I, is formed by joining a Beam of length 2*l to the right of another Beam of length l. The whole beam is fixed at both of its both end. A point load of magnitude P is also applied from the top at a distance of 2*l from starting point. >>> from sympy.physics.continuum_mechanics.beam import Beam >>> from sympy import symbols >>> E, I = symbols('E, I') >>> l=symbols('l', positive=True) >>> b1=Beam(l ,E,I) >>> b2=Beam(2*l ,E,I) >>> b=b1.join(b2,"hinge") >>> M1, A1, M2, A2, P = symbols('M1 A1 M2 A2 P') >>> b.apply_load(A1,0,-1) >>> b.apply_load(M1,0,-2) >>> b.apply_load(P,2*l,-1) >>> b.apply_load(A2,3*l,-1) >>> b.apply_load(M2,3*l,-2) >>> b.bc_slope=[(0,0), (3*l, 0)] >>> b.bc_deflection=[(0,0), (3*l, 0)] >>> b.solve_for_reaction_loads(M1, A1, M2, A2) >>> b.reaction_loads {A1: -5*P/18, A2: -13*P/18, M1: 5*P*l/18, M2: -4*P*l/9} >>> b.slope() Piecewise(((5*P*l*SingularityFunction(x, 0, 1)/18 - 5*P*SingularityFunction(x, 0, 2)/36 + 5*P*SingularityFunction(x, l, 2)/36)/(E*I), l >= x), ((P*l**2/18 - 4*P*l*SingularityFunction(-l + x, 2*l, 1)/9 - 5*P*SingularityFunction(-l + x, 0, 2)/36 + P*SingularityFunction(-l + x, l, 2)/2 - 13*P*SingularityFunction(-l + x, 2*l, 2)/36)/(E*I), x < 3*l)) >>> b.deflection() Piecewise(((5*P*l*SingularityFunction(x, 0, 2)/36 - 5*P*SingularityFunction(x, 0, 3)/108 + 5*P*SingularityFunction(x, l, 3)/108)/(E*I), l >= x), ((5*P*l**3/54 + P*l**2*(-l + x)/18 - 2*P*l*SingularityFunction(-l + x, 2*l, 2)/9 - 5*P*SingularityFunction(-l + x, 0, 3)/108 + P*SingularityFunction(-l + x, l, 3)/6 - 13*P*SingularityFunction(-l + x, 2*l, 3)/108)/(E*I), x < 3*l)) """ x = self.variable l = self._hinge_position E = self._elastic_modulus I = self._second_moment if isinstance(I, Piecewise): I1 = I.args[0][0] I2 = I.args[1][0] else: I1 = I2 = I load_1 = 0 # Load equation on first segment of composite beam load_2 = 0 # Load equation on second segment of composite beam # Distributing load on both segments for load in self.applied_loads: if load[1] < l: load_1 += load[0]*SingularityFunction(x, load[1], load[2]) if load[2] == 0: load_1 -= load[0]*SingularityFunction(x, load[3], load[2]) elif load[2] > 0: load_1 -= load[0]*SingularityFunction(x, load[3], load[2]) + load[0]*SingularityFunction(x, load[3], 0) elif load[1] == l: load_1 += load[0]*SingularityFunction(x, load[1], load[2]) load_2 += load[0]*SingularityFunction(x, load[1] - l, load[2]) elif load[1] > l: load_2 += load[0]*SingularityFunction(x, load[1] - l, load[2]) if load[2] == 0: load_2 -= load[0]*SingularityFunction(x, load[3] - l, load[2]) elif load[2] > 0: load_2 -= load[0]*SingularityFunction(x, load[3] - l, load[2]) + load[0]*SingularityFunction(x, load[3] - l, 0) h = Symbol('h') # Force due to hinge load_1 += h*SingularityFunction(x, l, -1) load_2 -= h*SingularityFunction(x, 0, -1) eq = [] shear_1 = integrate(load_1, x) shear_curve_1 = limit(shear_1, x, l) eq.append(shear_curve_1) bending_1 = integrate(shear_1, x) moment_curve_1 = limit(bending_1, x, l) eq.append(moment_curve_1) shear_2 = integrate(load_2, x) shear_curve_2 = limit(shear_2, x, self.length - l) eq.append(shear_curve_2) bending_2 = integrate(shear_2, x) moment_curve_2 = limit(bending_2, x, self.length - l) eq.append(moment_curve_2) C1 = Symbol('C1') C2 = Symbol('C2') C3 = Symbol('C3') C4 = Symbol('C4') slope_1 = S(1)/(E*I1)*(integrate(bending_1, x) + C1) def_1 = S(1)/(E*I1)*(integrate((E*I)*slope_1, x) + C1*x + C2) slope_2 = S(1)/(E*I2)*(integrate(integrate(integrate(load_2, x), x), x) + C3) def_2 = S(1)/(E*I2)*(integrate((E*I)*slope_2, x) + C4) for position, value in self.bc_slope: if position<l: eq.append(slope_1.subs(x, position) - value) else: eq.append(slope_2.subs(x, position - l) - value) for position, value in self.bc_deflection: if position<l: eq.append(def_1.subs(x, position) - value) else: eq.append(def_2.subs(x, position - l) - value) eq.append(def_1.subs(x, l) - def_2.subs(x, 0)) # Deflection of both the segments at hinge would be equal constants = list(linsolve(eq, C1, C2, C3, C4, h, *reactions)) reaction_values = list(constants[0])[5:] self._reaction_loads = dict(zip(reactions, reaction_values)) self._load = self._load.subs(self._reaction_loads) # Substituting constants and reactional load and moments with their corresponding values slope_1 = slope_1.subs({C1: constants[0][0], h:constants[0][4]}).subs(self._reaction_loads) def_1 = def_1.subs({C1: constants[0][0], C2: constants[0][1], h:constants[0][4]}).subs(self._reaction_loads) slope_2 = slope_2.subs({x: x-l, C3: constants[0][2], h:constants[0][4]}).subs(self._reaction_loads) def_2 = def_2.subs({x: x-l,C3: constants[0][2], C4: constants[0][3], h:constants[0][4]}).subs(self._reaction_loads) self._hinge_beam_slope = Piecewise((slope_1, x<=l), (slope_2, x<self.length)) self._hinge_beam_deflection = Piecewise((def_1, x<=l), (def_2, x<self.length))
def intersection(self, o): """ The intersection with other geometrical entity. Parameters ========== Point, Point3D, LinearEntity, LinearEntity3D, Plane Returns ======= List Examples ======== >>> from sympy import Point, Point3D, Line, Line3D, Plane >>> a = Plane(Point3D(1, 2, 3), normal_vector=(1, 1, 1)) >>> b = Point3D(1, 2, 3) >>> a.intersection(b) [Point3D(1, 2, 3)] >>> c = Line3D(Point3D(1, 4, 7), Point3D(2, 2, 2)) >>> a.intersection(c) [Point3D(2, 2, 2)] >>> d = Plane(Point3D(6, 0, 0), normal_vector=(2, -5, 3)) >>> e = Plane(Point3D(2, 0, 0), normal_vector=(3, 4, -3)) >>> d.intersection(e) [Line3D(Point3D(78/23, -24/23, 0), Point3D(147/23, 321/23, 23))] """ from sympy.geometry.line import LinearEntity, LinearEntity3D if not isinstance(o, GeometryEntity): o = Point(o, dim=3) if isinstance(o, Point): if o in self: return [o] else: return [] if isinstance(o, (LinearEntity, LinearEntity3D)): if o in self: p1, p2 = o.p1, o.p2 if isinstance(o, Segment): o = Segment3D(p1, p2) elif isinstance(o, Ray): o = Ray3D(p1, p2) elif isinstance(o, Line): o = Line3D(p1, p2) else: raise ValueError('unhandled linear entity: %s' % o.func) return [o] else: x, y, z = map(Dummy, 'xyz') t = Dummy() # unnamed else it may clash with a symbol in o a = Point3D(o.arbitrary_point(t)) b = self.equation(x, y, z) # TODO: Replace solve with solveset, when this line is tested c = solve(b.subs(list(zip((x, y, z), a.args))), t) if not c: return [] else: p = a.subs(t, c[0]) if p not in self: return [] # e.g. a segment might not intersect a plane return [p] if isinstance(o, Plane): if self.equals(o): return [self] if self.is_parallel(o): return [] else: x, y, z = map(Dummy, 'xyz') a, b = Matrix([self.normal_vector]), Matrix([o.normal_vector]) c = list(a.cross(b)) d = self.equation(x, y, z) e = o.equation(x, y, z) result = list(linsolve([d, e], x, y, z))[0] for i in (x, y, z): result = result.subs(i, 0) return [Line3D(Point3D(result), direction_ratio=c)]
def solve_slope_deflection(self): """ Solves the differnetial equation of buckling to determine the deflection and slope equations. Examples ======== A column of timber section is 8m long both ends being fixed. Young's modulus of the timber is E and second-moment I. The applied load on the column is 360KN. >>> from sympy.physics.continuum_mechanics.column import Column >>> from sympy import Symbol, symbols >>> E, I, P = symbols('E, I, P', positive=True) >>> c = Column(8, E, I, 360000, top="fixed", bottom="fixed") >>> c.end_conditions {'bottom': 'fixed', 'top': 'fixed'} >>> c.boundary_conditions {'deflection': [(0, 0), (8, 0)], 'slope': [(0, 0)]} >>> c.moment() -M + 360000*y(x) >>> c.solve_slope_deflection() >>> c.deflection() -M*cos(600*x/(sqrt(E)*sqrt(I)))/360000 + M/360000 >>> c.slope() M*sin(600*x/(sqrt(E)*sqrt(I)))/(600*sqrt(E)*sqrt(I)) """ y = Function('y') x = self._variable P = Symbol('P', positive=True) C1, C2 = symbols('C1, C2') E = self._elastic_modulus I = self._second_moment # differnetial equation of Column buckling eq = E * I * y(x).diff(x, 2) + self._moment defl_sol = dsolve(Eq(eq, 0), y(x)).args[1] slope_sol = defl_sol.diff(x) constants = list( linsolve([defl_sol.subs(x, 0), slope_sol.subs(x, 0)], C1, C2).args[0]) self._deflection = defl_sol.subs({C1: constants[0], C2: constants[1]}) self._slope = slope_sol.subs({C1: constants[0], C2: constants[1]}) # if deflection is zero, no buckling occurs, which is not the case, # so trying to solve for the constants differently if self._deflection == 0: self._deflection = defl_sol self._slope = slope_sol defl_eqs = [] # taking last two bounndary conditions which are actually # the initial boundary conditions. for point, value in self._boundary_conditions['deflection'][-2:]: defl_eqs.append(self._deflection.subs(x, point) - value) # solve for C1, C2 along with P solns = solve(defl_eqs, (P, C1, C2), dict=True) for sol in solns: if self._deflection.subs(sol) == 0: # removing trivial solutions solns.remove(sol) # checking if the constants are solved, and subtituting them in # the deflection and slope equation if C1 in solns[0].keys(): self._deflection = self._deflection.subs(C1, solns[0][C1]) self._slope = self._slope.subs(C1, solns[0][C1]) if C2 in solns[0].keys(): self._deflection = self._deflection.subs(C2, solns[0][C2]) self._slope = self._slope.subs(C2, solns[0][C2]) if P in solns[0].keys(): self._critical_load = solns[0][P]
def intersection(self, o): """ The intersection with other geometrical entity. Parameters ========== Point, Point3D, LinearEntity, LinearEntity3D, Plane Returns ======= List Examples ======== >>> from sympy import Point, Point3D, Line, Line3D, Plane >>> a = Plane(Point3D(1, 2, 3), normal_vector=(1, 1, 1)) >>> b = Point3D(1, 2, 3) >>> a.intersection(b) [Point3D(1, 2, 3)] >>> c = Line3D(Point3D(1, 4, 7), Point3D(2, 2, 2)) >>> a.intersection(c) [Point3D(2, 2, 2)] >>> d = Plane(Point3D(6, 0, 0), normal_vector=(2, -5, 3)) >>> e = Plane(Point3D(2, 0, 0), normal_vector=(3, 4, -3)) >>> d.intersection(e) [Line3D(Point3D(78/23, -24/23, 0), Point3D(147/23, 321/23, 23))] """ from sympy.geometry.line import LinearEntity, LinearEntity3D if not isinstance(o, GeometryEntity): o = Point(o, dim=3) if isinstance(o, Point): if o in self: return [o] else: return [] if isinstance(o, (LinearEntity, LinearEntity3D)): # recast to 3D p1, p2 = o.p1, o.p2 if isinstance(o, Segment): o = Segment3D(p1, p2) elif isinstance(o, Ray): o = Ray3D(p1, p2) elif isinstance(o, Line): o = Line3D(p1, p2) else: raise ValueError("unhandled linear entity: %s" % o.func) if o in self: return [o] else: t = Dummy() # unnamed else it may clash with a symbol in o a = Point3D(o.arbitrary_point(t)) p1, n = self.p1, Point3D(self.normal_vector) # TODO: Replace solve with solveset, when this line is tested c = solve((a - p1).dot(n), t) if not c: return [] else: c = [i for i in c if i.is_real is not False] if len(c) > 1: c = [i for i in c if i.is_real] if len(c) != 1: raise Undecidable("not sure which point is real") p = a.subs(t, c[0]) if p not in o: return [] # e.g. a segment might not intersect a plane return [p] if isinstance(o, Plane): if self.equals(o): return [self] if self.is_parallel(o): return [] else: x, y, z = map(Dummy, "xyz") a, b = Matrix([self.normal_vector]), Matrix([o.normal_vector]) c = list(a.cross(b)) d = self.equation(x, y, z) e = o.equation(x, y, z) result = list(linsolve([d, e], x, y, z))[0] for i in (x, y, z): result = result.subs(i, 0) return [Line3D(Point3D(result), direction_ratio=c)]
def b(i): i = i + 1 return integrate(b_intern, 0, 1, i) M = zeros(n, n + 1) for i in range(0, n): M[i, n] = b(i) M[i, i] = m(i, i) if (i - 1) >= 0: M[i, i - 1] = m(i, i - 1) if (i + 1) < n: M[i, i + 1] = m(i, i + 1) coeficients = symbols('a_0:{}'.format(n)) solution, = linsolve(M, coeficients) def function(solution, x): value = 0 i = 0 for c in solution: value += c * fi(i + 1, x) i = i + 1 return value def function_original(x): return ((x - 1) * (e**(-x) - 1))
def poly_solve(eqns_list, unknowns): """ Description ----------- Custom solver for linear system of symbolic equations. As Sympy solve() function gets pretty slow on not that big systems (~10 equations and 10 unknowns containing symbolic variables), this solver might be faster for big systems. The most important feature is that it is possible to keep track of the solving process (printed on the console), so the user can have an idea of the remaining time. This solver might however be slower if there are no symbolic variables. Parameters ---------- eqns_list : list of Sympy expressions List of expressions (considered equal to 0) unknowns : sympy symbol list Variables to solve for Returns ------- solution : dict Dictionary containing solutions """ eqns = eqns_list.copy() # Choosing solver nb_sym = 0 for eq in eqns: fs = eq.free_symbols fs.difference_update(unknowns) if len(fs) > 0: nb_sym += 1 custom_solver = (nb_sym > 0) if custom_solver: # System solutions sol = {} solr = {xi: 0 for xi in unknowns} # Found solutions found_vars = [] for w, eqn in enumerate(eqns): print("Trajectory generation - Finding solution: " + ("%.0f" % (100 * w / len(eqns))) + " %") variable = 0 for var in unknowns: if var in eqn.free_symbols and var not in found_vars: variable = var break if variable == 0: continue sol[variable] = list(linsolve([eqn], [variable]))[0][0] solr[variable] = sol[variable] for i, eq in enumerate(eqns): eqns[i] = eq.subs(sol).simplify(rational=False) found_vars.append(variable) # Simplifying solution # dct = [[len(solr[a].free_symbols) for a in solr], # [a for a in solr]] dct = [] for a in solr: try: sym_len = len(solr[a].free_symbols) except AttributeError: sym_len = 0 dct.append([sym_len, a]) # dct = list(map(list, zip(*dct))) dct.sort(key=lambda x: x[0]) for j, s in enumerate(dct): print("Trajectory generation - Simplifying solution: " + "%.0f" % (100 * j / len(dct)) + " %") for i, sol_i in enumerate(solr): try: solr[sol_i] = solr[sol_i].subs(s[1], solr[s[1]]) \ .simplify(rational=False).factor().cancel() \ .nsimplify(tolerance=1e-10).evalf() except AttributeError: pass print("Done.") return solr else: return solve(eqns, unknowns)
from sympy import symbols, Matrix from sympy.solvers import linsolve l, C, D = symbols('l C D') A = Matrix([[2, 3 * l, 4 * l**2, C], [1, 2 * l, 3 * l**2, C / 2], [8, 18 * l, 144 / 5 * l**2, D]]) a2, a3, a4 = symbols("a2 a3 a4") sol, = linsolve(A, [a2, a3, a4]) print(sol)