def lineseg_integrate(polygon, index, line_seg, expr, degree): """Helper function to compute the line integral of `expr` over `line_seg` Parameters =========== polygon : Face of a 3-Polytope index : index of line_seg in polygon line_seg : Line Segment >>> from sympy.integrals.intpoly import lineseg_integrate >>> polygon = [(0, 5, 0), (5, 5, 0), (5, 5, 5), (0, 5, 5)] >>> line_seg = [(0, 5, 0), (5, 5, 0)] >>> lineseg_integrate(polygon, 0, line_seg, 1, 0) 5 """ if expr == S.Zero: return S.Zero result = S.Zero x0 = line_seg[0] distance = norm(tuple([line_seg[1][i] - line_seg[0][i] for i in range(3)])) if isinstance(expr, Expr): expr_dict = {x: line_seg[1][0], y: line_seg[1][1], z: line_seg[1][2]} result += distance * expr.subs(expr_dict) else: result += distance * expr expr = diff(expr, x) * x0[0] + diff(expr, y) * x0[1] +\ diff(expr, z) * x0[2] result += lineseg_integrate(polygon, index, line_seg, expr, degree - 1) result /= (degree + 1) return result
def get_parameter(parametrization_type): if parametrization_type == 0: # normal parametrization # Get the current slider value t0 = t_value_input.value elif parametrization_type == 1: # arc length parametrization f_x_str = x_component_input.value f_y_str = y_component_input.value f_x_sym = arc_functions.sym_parser(f_x_str) f_y_sym = arc_functions.sym_parser(f_y_str) from sympy.core import diff df_x_sym = diff(f_x_sym) df_y_sym = diff(f_y_sym) from sympy.abc import t from sympy import lambdify df_x = lambdify(t, df_x_sym, ['numpy']) df_y = lambdify(t, df_y_sym, ['numpy']) # compute arc length arc_length = arc_functions.arclength(df_x, df_y, arc_settings.t_value_max) # map input interval [t_value_min,t_value_max] to [0,arc_length] width_t = (arc_settings.t_value_max - arc_settings.t_value_min) t_fraction = (t_value_input.value - arc_settings.t_value_min) / width_t t_arc_length = t_fraction * arc_length # compute corresponding value on original parametrization t0 = arc_functions.s_inverse(df_x, df_y, t_arc_length) return t0
def calc_area(f_x_sym, f_y_sym, t_val): from sympy.abc import t f_x = lambdify(t, f_x_sym,['numpy']) f_y = lambdify(t, f_y_sym, ['numpy']) df_x = lambdify(t, diff(f_x_sym), ['numpy']) df_y = lambdify(t, diff(f_y_sym), ['numpy']) integrand = lambda tau: f_x(tau)*df_y(tau)-df_x(tau)*f_y(tau) return abs(0.5 * quad(integrand, 0, t_val)[0])
def calc_area(f_x_sym, f_y_sym, t_val): from sympy.abc import t f_x = lambdify(t, f_x_sym, ['numpy']) f_y = lambdify(t, f_y_sym, ['numpy']) df_x = lambdify(t, diff(f_x_sym), ['numpy']) df_y = lambdify(t, diff(f_y_sym), ['numpy']) integrand = lambda tau: f_x(tau) * df_y(tau) - df_x(tau) * f_y(tau) return abs(0.5 * quad(integrand, 0, t_val)[0])
def integration_reduction(facets, index, a, b, expr, dims, degree): """Helper method for main_integrate. Returns the value of the input expression evaluated over the polytope facet referenced by a given index. Parameters =========== facets : List of facets of the polytope. index : Index referencing the facet to integrate the expression over. a : Hyperplane parameter denoting direction. b : Hyperplane parameter denoting distance. expr : The expression to integrate over the facet. dims : List of symbols denoting axes. degree : Degree of the homogeneous polynomial. Examples ======== >>> from sympy.abc import x, y >>> from sympy.integrals.intpoly import integration_reduction,\ hyperplane_parameters >>> from sympy.geometry.point import Point >>> from sympy.geometry.polygon import Polygon >>> triangle = Polygon(Point(0, 3), Point(5, 3), Point(1, 1)) >>> facets = triangle.sides >>> a, b = hyperplane_parameters(triangle)[0] >>> integration_reduction(facets, 0, a, b, 1, (x, y), 0) 5 """ expr = _sympify(expr) if expr.is_zero: return expr value = S.Zero x0 = facets[index].points[0] m = len(facets) gens = (x, y) inner_product = diff(expr, gens[0]) * x0[0] + diff(expr, gens[1]) * x0[1] if inner_product != 0: value += integration_reduction(facets, index, a, b, inner_product, dims, degree - 1) value += left_integral2D(m, index, facets, x0, expr, gens) return value / (len(dims) + degree - 1)
def polygon_integrate(facet, hp_param, index, facets, vertices, expr, degree): """Helper function to integrate the input uni/bi/trivariate polynomial over a certain face of the 3-Polytope. Parameters ========== facet : Particular face of the 3-Polytope over which ``expr`` is integrated. index : The index of ``facet`` in ``facets``. facets : Faces of the 3-Polytope(expressed as indices of `vertices`). vertices : Vertices that constitute the facet. expr : The input polynomial. degree : Degree of ``expr``. Examples ======== >>> from sympy.integrals.intpoly import polygon_integrate >>> cube = [[(0, 0, 0), (0, 0, 5), (0, 5, 0), (0, 5, 5), (5, 0, 0),\ (5, 0, 5), (5, 5, 0), (5, 5, 5)],\ [2, 6, 7, 3], [3, 7, 5, 1], [7, 6, 4, 5], [1, 5, 4, 0],\ [3, 1, 0, 2], [0, 4, 6, 2]] >>> facet = cube[1] >>> facets = cube[1:] >>> vertices = cube[0] >>> polygon_integrate(facet, [(0, 1, 0), 5], 0, facets, vertices, 1, 0) -25 """ expr = S(expr) if expr.is_zero: return S.Zero result = S.Zero x0 = vertices[facet[0]] for i in range(len(facet)): side = (vertices[facet[i]], vertices[facet[(i + 1) % len(facet)]]) result += distance_to_side(x0, side, hp_param[0]) *\ lineseg_integrate(facet, i, side, expr, degree) if not expr.is_number: expr = diff(expr, x) * x0[0] + diff(expr, y) * x0[1] +\ diff(expr, z) * x0[2] result += polygon_integrate(facet, hp_param, index, facets, vertices, expr, degree - 1) result /= (degree + 2) return result
def _eval_rewrite_as_Heaviside(self, *args, **kwargs): ''' Rewrites a Singularity Function expression using Heavisides and DiracDeltas. ''' x = self.args[0] a = self.args[1] n = sympify(self.args[2]) if n == -2: return diff(Heaviside(x - a), x.free_symbols.pop(), 2) if n == -1: return diff(Heaviside(x - a), x.free_symbols.pop(), 1) if n.is_nonnegative: return (x - a)**n*Heaviside(x - a)
def _eval_rewrite_as_Heaviside(self, *args, **kwargs): ''' Rewrites a Singularity Function expression using Heavisides and DiracDeltas. ''' x = self.args[0] a = self.args[1] n = sympify(self.args[2]) if n == -2: return diff(Heaviside(x - a), x.free_symbols.pop(), 2) if n == -1: return diff(Heaviside(x - a), x.free_symbols.pop(), 1) if n.is_nonnegative: return (x - a)**n * Heaviside(x - a)
def secondDerivativeTest(self, point): """Second Derivative Test for 1D Dynamical System Raises ====== ValueError When the point that is passed is not a fixed point Examples ======== >>> from dynamical1D import DynamicalSystem1D >>> zDot = DynamicalSystem1D((z+1)*(z-1)*(z**2), z) >>> zDot.secondDerivativeTest(-1) 'Stable' >>> zDot.secondDerivativeTest(0) 'Semi-Stable' >>> zDot.secondDerivativeTest(1) 'Unstable' """ if point not in self.fixedPoints: raise ValueError( "Cannot Apply the Second Derivative Test if Passed Point is not a Fixed Point" ) value = diff(self.system, self.parameter).subs(self.parameter, point) if value > 0: return "Unstable" if value < 0: return "Stable" return "Semi-Stable"
def integration_reduction(facets, index, a, b, expr, dims, degree): """Helper method for main_integrate. Returns the value of the input expression evaluated over the polytope facet referenced by a given index. Parameters =========== facets : List of facets of the polytope. index : Index referencing the facet to integrate the expression over. a : Hyperplane parameter denoting direction. b : Hyperplane parameter denoting distance. expr : The expression to integrate over the facet. dims : List of symbols denoting axes. degree : Degree of the homogeneous polynomial. Examples ======== >>> from sympy.abc import x, y >>> from sympy.integrals.intpoly import integration_reduction,\ hyperplane_parameters >>> from sympy.geometry.point import Point >>> from sympy.geometry.polygon import Polygon >>> triangle = Polygon(Point(0, 3), Point(5, 3), Point(1, 1)) >>> facets = triangle.sides >>> a, b = hyperplane_parameters(triangle)[0] >>> integration_reduction(facets, 0, a, b, 1, (x, y), 0) 5 """ if expr == S.Zero: return expr value = S.Zero x0 = facets[index].points[0] m = len(facets) gens = (x, y) inner_product = diff(expr, gens[0]) * x0[0] + diff(expr, gens[1]) * x0[1] if inner_product != 0: value += integration_reduction(facets, index, a, b, inner_product, dims, degree - 1) value += left_integral2D(m, index, facets, x0, expr, gens) return value/(len(dims) + degree - 1)
def polygon_integrate(facet, hp_param, index, facets, vertices, expr, degree): """Helper function to integrate the input uni/bi/trivariate polynomial over a certain face of the 3-Polytope. Parameters =========== facet : Particular face of the 3-Polytope over which `expr` is integrated index : The index of `facet` in `facets` facets : Faces of the 3-Polytope(expressed as indices of `vertices`) vertices : Vertices that constitute the facet expr : The input polynomial degree : Degree of `expr` Examples ======== >>> from sympy.abc import x, y >>> from sympy.integrals.intpoly import polygon_integrate >>> cube = [[(0, 0, 0), (0, 0, 5), (0, 5, 0), (0, 5, 5), (5, 0, 0),\ (5, 0, 5), (5, 5, 0), (5, 5, 5)],\ [2, 6, 7, 3], [3, 7, 5, 1], [7, 6, 4, 5], [1, 5, 4, 0],\ [3, 1, 0, 2], [0, 4, 6, 2]] >>> facet = cube[1] >>> facets = cube[1:] >>> vertices = cube[0] >>> polygon_integrate(facet, [(0, 1, 0), 5], 0, facets, vertices, 1, 0) -25 """ expr = S(expr) if expr == S.Zero: return S.Zero result = S.Zero x0 = vertices[facet[0]] for i in range(len(facet)): side = (vertices[facet[i]], vertices[facet[(i + 1) % len(facet)]]) result += distance_to_side(x0, side, hp_param[0]) *\ lineseg_integrate(facet, i, side, expr, degree) if not expr.is_number: expr = diff(expr, x) * x0[0] + diff(expr, y) * x0[1] +\ diff(expr, z) * x0[2] result += polygon_integrate(facet, hp_param, index, facets, vertices, expr, degree - 1) result /= (degree + 2) return result
def polygon_integrate(facet, hp_param, index, facets, vertices, expr, degree): """Helper function to integrate the input uni/bi/trivariate polynomial over a certain face of the 3-Polytope. Parameters =========== facet : Particular face of the 3-Polytope over which `expr` is integrated index : The index of `facet` in `facets` facets : Faces of the 3-Polytope(expressed as indices of `vertices`) vertices : Vertices that constitute the facet expr : The input polynomial degree : Degree of `expr` >>> from sympy.abc import x, y >>> from sympy.integrals.intpoly import polygon_integrate >>> cube = [[(0, 0, 0), (0, 0, 5), (0, 5, 0), (0, 5, 5), (5, 0, 0),\ (5, 0, 5), (5, 5, 0), (5, 5, 5)],\ [2, 6, 7, 3], [3, 7, 5, 1], [7, 6, 4, 5], [1, 5, 4, 0],\ [3, 1, 0, 2], [0, 4, 6, 2]] >>> facet = cube[1] >>> facets = cube[1:] >>> vertices = cube[0] >>> polygon_integrate(facet, [(0, 1, 0), 5], 0, facets, vertices, 1, 0) -25 """ if expr == S.Zero: return S.Zero result = S.Zero m = len(facets) x0 = vertices[facet[0]] for i in range(len(facet)): side = (facet[i], facet[(i + 1) % len(facet)]) for j in range(m): if j != index and len(set(side).intersection(set(facets[j]))) == 2: side = (vertices[side[0]], vertices[side[1]]) result += distance_to_side(x0, side, hp_param[0]) *\ lineseg_integrate(facet, i, side, expr, degree) expr = diff(expr, x) * x0[0] + diff(expr, y) * x0[1] +\ diff(expr, z) * x0[2] result += polygon_integrate(facet, hp_param, index, facets, vertices, expr, degree - 1) result /= (degree + 2) return result
def _do(f, ab): dab_dsym = diff(ab, sym) if not dab_dsym: return S.Zero if isinstance(f, Integral): limits = [(x, x) if (len(l) == 1 and l[0] == x) else l for l in f.limits] f = Integral(f.function, *limits) return f.subs(x, ab) * dab_dsym
def _do(f, ab): dab_dsym = diff(ab, sym) if not dab_dsym: return S.Zero if isinstance(f, Integral): limits = [(x, x) if (len(l) == 1 and l[0] == x) else l for l in f.limits] f = Integral(f.function, *limits) return f.subs(x, ab)*dab_dsym
def is_linear(expr): syms = expr.free_symbols for x in syms: for y in syms: try: if not sympy.Eq(sympy.diff(expr, x, y), 0): return False except TypeError: return False return True
def _eval_derivative(self, sym): """Evaluate the derivative of the current Integral object. We follow these steps: (1) If sym is not part of the function nor the integration limits, return 0 (2) Check for a possible application of the Fundamental Theorem of Calculus [1] (3) Derive under the integral sign [2] References: [1] http://en.wikipedia.org/wiki/Fundamental_theorem_of_calculus [2] http://en.wikipedia.org/wiki/Differentiation_under_the_integral_sign """ if not sym in self.atoms(Symbol): return S.Zero if (sym, None) in self.limits: # case undefinite integral if len(self.limits) == 1: return self.function else: _limits = list(self.limits) _limits.pop(_limits.index((sym, None))) return Integral(self.function, *tuple(_limits)) # diff under the integral sign # we do not check for regularity conditions (TODO), see issue 1116 if len(self.limits) > 1: # TODO:implement the multidimensional case raise NotImplementedError int_var = self.limits[0][0] lower_limit, upper_limit = self.limits[0][1] if sym == int_var: sym = Symbol(str(int_var), dummy=True) return ( self.function.subs(int_var, upper_limit) * diff(upper_limit, sym) - self.function.subs(int_var, lower_limit) * diff(lower_limit, sym) + integrate(diff(self.function, sym), (int_var, lower_limit, upper_limit)) )
def test_sho_R_nl(): omega, r = symbols('omega r') l = symbols('l', integer=True) u = Function('u') # check that it obeys the Schrodinger equation for n in range(5): schreq = ( -diff(u(r), r, 2)/2 + ((l*(l+1))/(2*r**2) + omega**2*r**2/2 - E_nl(n, l, omega))*u(r) ) result = schreq.subs(u(r), r*R_nl(n, l, omega/2, r)) assert simplify(result.doit()) == 0
def calculate_tangent(f_x_str, f_y_str, t0): f_x_sym = sym_parser(f_x_str) f_y_sym = sym_parser(f_y_str) f_x = parser(f_x_str) f_y = parser(f_y_str) from sympy.core import diff from sympy.abc import t df_x_sym = diff(f_x_sym) df_y_sym = diff(f_y_sym) df_x = lambdify(t, df_x_sym, ['numpy']) df_y = lambdify(t, df_y_sym, ['numpy']) x = np.array([f_x(t0)],dtype=np.float64) y = np.array([f_y(t0)],dtype=np.float64) u = np.array([df_x(t0)],dtype=np.float64) v = np.array([df_y(t0)],dtype=np.float64) return x,y,u,v
def simplify(self, x): """simplify(self, x) Compute a simplified representation of the function using property number 4. x can be: - a symbol Examples ======== >>> from sympy import DiracDelta >>> from sympy.abc import x, y >>> DiracDelta(x*y).simplify(x) DiracDelta(x)/Abs(y) >>> DiracDelta(x*y).simplify(y) DiracDelta(y)/Abs(x) >>> DiracDelta(x**2 + x - 2).simplify(x) DiracDelta(x - 1)/3 + DiracDelta(x + 2)/3 See Also ======== is_simple, Diracdelta """ from sympy.polys.polyroots import roots if not self.args[0].has(x) or (len(self.args) > 1 and self.args[1] != 0): return self try: argroots = roots(self.args[0], x) result = 0 valid = True darg = abs(diff(self.args[0], x)) for r, m in argroots.items(): if r.is_real is not False and m == 1: result += self.func(x - r) / darg.subs(x, r) else: # don't handle non-real and if m != 1 then # a polynomial will have a zero in the derivative (darg) # at r valid = False break if valid: return result except PolynomialError: pass return self
def calculate_tangent(f_x_str, f_y_str, t0): f_x_sym = sym_parser(f_x_str) f_y_sym = sym_parser(f_y_str) f_x = parser(f_x_str) f_y = parser(f_y_str) from sympy.core import diff from sympy.abc import t df_x_sym = diff(f_x_sym) df_y_sym = diff(f_y_sym) df_x = lambdify(t, df_x_sym, ['numpy']) df_y = lambdify(t, df_y_sym, ['numpy']) x = np.array([f_x(t0)], dtype=np.float64) y = np.array([f_y(t0)], dtype=np.float64) u = np.array([df_x(t0)], dtype=np.float64) v = np.array([df_y(t0)], dtype=np.float64) return x, y, u, v
def _eval_derivative(self, sym): """Evaluate the derivative of the current Integral object. We follow these steps: (1) If sym is not part of the function nor the integration limits, return 0 (2) Check for a possible application of the Fundamental Theorem of Calculus [1] (3) Derive under the integral sign [2] References: [1] http://en.wikipedia.org/wiki/Fundamental_theorem_of_calculus [2] http://en.wikipedia.org/wiki/Differentiation_under_the_integral_sign """ if not sym in self.atoms(Symbol): return S.Zero if (sym, None) in self.limits: #case undefinite integral if len(self.limits) == 1: return self.function else: _limits = list(self.limits) _limits.pop(_limits.index((sym, None))) return Integral(self.function, *tuple(_limits)) #diff under the integral sign #we do not check for regularity conditions (TODO), see issue 1116 if len(self.limits) > 1: # TODO:implement the multidimensional case raise NotImplementedError int_var = self.limits[0][0] lower_limit, upper_limit = self.limits[0][1] if sym == int_var: sym = Symbol(str(int_var), dummy=True) return self.function.subs(int_var, upper_limit)*diff(upper_limit, sym) - \ self.function.subs(int_var, lower_limit)*diff(lower_limit, sym) + \ integrate(diff(self.function, sym), (int_var, lower_limit, upper_limit))
def test_sho_R_nl(): omega, r = symbols('omega r') l = symbols('l', integer=True) u = Function('u') # check that it obeys the Schrodinger equation for n in range(5): schreq = (-diff(u(r), r, 2) / 2 + ( (l * (l + 1)) / (2 * r**2) + omega**2 * r**2 / 2 - E_nl(n, l, omega)) * u(r)) result = schreq.subs(u(r), r * R_nl(n, l, omega / 2, r)) assert simplify(result.doit()) == 0
def simplify(self, x): """simplify(self, x) Compute a simplified representation of the function using property number 4. x can be: - a symbol Examples ======== >>> from sympy import DiracDelta >>> from sympy.abc import x, y >>> DiracDelta(x*y).simplify(x) DiracDelta(x)/Abs(y) >>> DiracDelta(x*y).simplify(y) DiracDelta(y)/Abs(x) >>> DiracDelta(x**2 + x - 2).simplify(x) DiracDelta(x - 1)/3 + DiracDelta(x + 2)/3 See Also ======== is_simple, Directdelta """ from sympy.polys.polyroots import roots if not self.args[0].has(x) or (len(self.args) > 1 and self.args[1] != 0 ): return self try: argroots = roots(self.args[0], x) result = 0 valid = True darg = abs(diff(self.args[0], x)) for r, m in argroots.items(): if r.is_real is not False and m == 1: result += self.func(x - r)/darg.subs(x, r) else: # don't handle non-real and if m != 1 then # a polynomial will have a zero in the derivative (darg) # at r valid = False break if valid: return result except PolynomialError: pass return self
def simplify(self, x): """simplify(self, x) Compute a simplified representation of the function using property number 4. x can be: - a symbol Examples ======== >>> from sympy import DiracDelta >>> from sympy.abc import x, y >>> DiracDelta(x*y).simplify(x) DiracDelta(x)/Abs(y) >>> DiracDelta(x*y).simplify(y) DiracDelta(y)/Abs(x) >>> DiracDelta(x**2 + x - 2).simplify(x) DiracDelta(x - 1)/3 + DiracDelta(x + 2)/3 See Also ======== is_simple, Directdelta """ from sympy.polys.polyroots import roots if not self.args[0].has(x) or (len(self.args) > 1 and self.args[1] != 0): return self try: argroots = roots(self.args[0], x, \ multiple=True) result = 0 valid = True darg = diff(self.args[0], x) for r in argroots: #should I care about multiplicities of roots? if r.is_real and not darg.subs(x, r).is_zero: result = result + DiracDelta(x - r) / abs(darg.subs(x, r)) else: valid = False break if valid: return result except PolynomialError: pass return self
def simplify(self, x): """simplify(self, x) Compute a simplified representation of the function using property number 4. x can be: - a symbol Examples ======== >>> from sympy import DiracDelta >>> from sympy.abc import x, y >>> DiracDelta(x*y).simplify(x) DiracDelta(x)/Abs(y) >>> DiracDelta(x*y).simplify(y) DiracDelta(y)/Abs(x) >>> DiracDelta(x**2 + x - 2).simplify(x) DiracDelta(x - 1)/3 + DiracDelta(x + 2)/3 See Also ======== is_simple, Directdelta """ from sympy.polys.polyroots import roots if not self.args[0].has(x) or (len(self.args)>1 and self.args[1] != 0 ): return self try: argroots = roots(self.args[0], x, \ multiple=True) result = 0 valid = True darg = diff(self.args[0], x) for r in argroots: #should I care about multiplicities of roots? if r.is_real and not darg.subs(x,r).is_zero: result = result + DiracDelta(x - r)/abs(darg.subs(x,r)) else: valid = False break if valid: return result except PolynomialError: pass return self
def length(self): """The curve length. Examples ======== >>> from sympy.geometry.curve import Curve >>> from sympy.abc import t >>> Curve((t, t), (t, 0, 1)).length sqrt(2) """ integrand = sqrt(sum(diff(func, self.limits[0])**2 for func in self.functions)) return integrate(integrand, self.limits)
def length(self): """The curve length. Examples ======== >>> from sympy.geometry.curve import Curve >>> from sympy import cos, sin >>> from sympy.abc import t >>> Curve((t, t), (t, 0, 1)).length sqrt(2) """ integrand = sqrt(sum(diff(func, self.limits[0])**2 for func in self.functions)) return integrate(integrand, self.limits)
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 simplify(self, x): """simplify(self, x) Compute a simplified representation of the function using property number 4. x can be: - a symbol Examples -------- >>> from sympy import * >>> x, y = symbols('xy') >>> DiracDelta(x*y).simplify(x) DiracDelta(x)/abs(y) >>> DiracDelta(x*y).simplify(y) DiracDelta(y)/abs(x) >>> DiracDelta(x**2+x-2).simplify(x) DiracDelta(-1 + x)/3 + DiracDelta(2 + x)/3 """ if not self.args[0].has(x) or (len(self.args) > 1 and self.args[1] != 0): return self try: argroots = sympy.polys.rootfinding.roots(self.args[0],x, \ multiple=True) result = 0 valid = True darg = diff(self.args[0], x) for r in argroots: #should I care about multiplicities of roots? if r.is_real and not darg.subs(x, r).is_zero: result = result + DiracDelta(x - r) / abs(darg.subs(x, r)) else: valid = False break if valid: return result except Exception, e: print e raise pass
def line_integrate(field, curve, vars): """line_integrate(field, Curve, variables) Compute the line integral. Examples ======== >>> from sympy import Curve, line_integrate, E, ln >>> from sympy.abc import x, y, t >>> C = Curve([E**t + 1, E**t - 1], (t, 0, ln(2))) >>> line_integrate(x + y, C, [x, y]) 3*sqrt(2) See Also ======== integrate, Integral """ F = sympify(field) if not F: raise ValueError( "Expecting function specifying field as first argument.") if not isinstance(curve, Curve): raise ValueError("Expecting Curve entity as second argument.") if not is_sequence(vars): raise ValueError("Expecting ordered iterable for variables.") if len(curve.functions) != len(vars): raise ValueError("Field variable size does not match curve dimension.") if curve.parameter in vars: raise ValueError("Curve parameter clashes with field parameters.") # Calculate derivatives for line parameter functions # F(r) -> F(r(t)) and finally F(r(t)*r'(t)) Ft = F dldt = 0 for i, var in enumerate(vars): _f = curve.functions[i] _dn = diff(_f, curve.parameter) # ...arc length dldt = dldt + (_dn * _dn) Ft = Ft.subs(var, _f) Ft = Ft * sqrt(dldt) integral = Integral(Ft, curve.limits).doit(deep=False) return integral
def simplify(self, x): """simplify(self, x) Compute a simplified representation of the function using property number 4. x can be: - a symbol Examples -------- >>> from sympy import * >>> x, y = symbols('xy') >>> DiracDelta(x*y).simplify(x) 1/abs(y)*DiracDelta(x) >>> DiracDelta(x*y).simplify(y) 1/abs(x)*DiracDelta(y) >>> DiracDelta(x**2+x-2).simplify(x) 1/3*DiracDelta(-1 + x) + 1/3*DiracDelta(2 + x) """ if not self.args[0].has(x) or (len(self.args)>1 and self.args[1] != 0 ): return self try: argroots = sympy.polys.rootfinding.roots(self.args[0],x, \ multiple=True) result = 0 valid = True darg = diff(self.args[0], x) for r in argroots: #should I care about multiplicities of roots? if r.is_real and not darg.subs(x,r).is_zero: result = result + DiracDelta(x - r)/abs(darg.subs(x,r)) else: valid = False break if valid: return result except Exception,e : print e raise pass
def diffV(self): """The derivative of each function in the curve Examples ======== >>> from curve import Curve >>> from sympy import sin, cos >>> alpha = Curve((sin(x), cos(x), 0), x) >>> alpha.diffV() Curve((cos(x), -sin(x), 0), x) """ result = [] for func in self.functions: result.append(diff(func,self.parameter)) return Curve(tuple(result),self.parameter)
def line_integrate(field, curve, vars): """line_integrate(field, Curve, variables) Compute the line integral. Examples -------- >>> from sympy import * >>> x, y, t = symbols('xyt') >>> C = Curve([E**t + 1, E**t - 1], (t, 0, ln(2))) >>> line_integrate(x + y, C, [x, y]) 3*sqrt(2) """ F = sympify(field) if not F: raise ValueError( "Expecting function specifying field as first argument.") if not isinstance(curve, Curve): raise ValueError("Expecting Curve entity as second argument.") if not isinstance(vars, (list, tuple)): raise ValueError("Expecting list/tuple for variables.") if len(curve.functions) != len(vars): raise ValueError("Field variable size does not match curve dimension.") if curve.parameter in vars: raise ValueError("Curve parameter clashes with field parameters.") # Calculate derivatives for line parameter functions # F(r) -> F(r(t)) and finally F(r(t)*r'(t)) Ft = F dldt = 0 for i, var in enumerate(vars): _f = curve.functions[i] _dn = diff(_f, curve.parameter) # ...arc length dldt = dldt + (_dn * _dn) Ft = Ft.subs(var, _f) Ft = Ft * dldt**(S(1) / 2) integral = Integral(Ft, curve.limits).doit() return integral
def line_integrate(field, curve, vars): """line_integrate(field, Curve, variables) Compute the line integral. Examples -------- >>> from sympy import * >>> x, y, t = symbols('xyt') >>> C = Curve([E**t + 1, E**t - 1], (t, 0, ln(2))) >>> line_integrate(x + y, C, [x, y]) 3*sqrt(2) """ F = sympify(field) if not F: raise ValueError("Expecting function specifying field as first argument.") if not isinstance(curve, Curve): raise ValueError("Expecting Curve entity as second argument.") if not isinstance(vars, (list, tuple)): raise ValueError("Expecting list/tuple for variables.") if len(curve.functions) != len(vars): raise ValueError("Field variable size does not match curve dimension.") if curve.parameter in vars: raise ValueError("Curve parameter clashes with field parameters.") # Calculate derivatives for line parameter functions # F(r) -> F(r(t)) and finally F(r(t)*r'(t)) Ft = F dldt = 0 for i, var in enumerate(vars): _f = curve.functions[i] _dn = diff(_f, curve.parameter) # ...arc length dldt = dldt + (_dn * _dn) Ft = Ft.subs(var, _f) Ft = Ft * dldt**(S(1)/2) integral = Integral(Ft, curve.limits).doit() return integral
def singular_points(self): """ Returns a set of singular points of the region. The singular points are those points on the region where all partial derivatives vanish. Examples ======== >>> from sympy.abc import x, y >>> from sympy.vector import ImplicitRegion >>> I = ImplicitRegion((x, y), (y-1)**2 -x**3 + 2*x**2 -x) >>> I.singular_points() {(1, 1)} """ eq_list = [self.equation] for var in self.variables: eq_list += [diff(self.equation, var)] return nonlinsolve(eq_list, list(self.variables))
def grad(f, args, g=None, output_type=None): """Return the vector field gradient of a function f(x). Examples: ========= >>> from tensor_analysis.tensor_fields import grad >>> from sympy import symbols, sin >>> from tensor_analysis.arraypy import Arraypy >>> x1, x2, x3 = symbols('x1 x2 x3') f it's a function the differential of that is calculated: >>> f=x1**2*x2 + sin(x2*x3 - x2) args it's a list of symbol arguments of function of f. It can be in list, array of arraypy or contravariant tensor: >>> args=[x1,x2,x3] g - optional parameter, metric tensor, which can be a matrix "Matrix", array of arraypy or covariant tensor: >>> g=Arraypy([2,3,1]) >>> g_t=g.to_tensor((-1,-1)) >>> g_t[1,1]=2 >>> g_t[1,2]=1 >>> g_t[1,3]=0 >>> g_t[2,1]=1 >>> g_t[2,2]=3 >>> g_t[2,3]=0 >>> g_t[3,1]=0 >>> g_t[3,2]=0 >>> g_t[3,3]=1 output _ type it is an optional parameter accepting symbol value of 'l', 'a' or 't' and indicative on the type of result of calculations: - 'l' it is a result as a list(list); - 'a' it is a result as an unidimensional array of arraypy; - 't' it is a result as an unidimensional covariant tensor. Gradient: >>> gr=grad(f,args,g_t,'a') >>> print(gr) -x1**2/5 + 6*x1*x2/5 - (x3 - 1)*cos(x2*x3 - x2)/5 2*x1**2/5 - 2*x1*x2/5 + \ 2*(x3 - 1)*cos(x2*x3 - x2)/5 x2*cos(x2*x3 - x2) """ # Handling of a vector of arguments check_vector_of_arguments(args) # The definition of the start index if isinstance(args, list): idx_args = 0 else: idx_args = args.start_index[0] # Handling of the metric tensor # 1. if g is not NULL if g is not None: if output_type is None: output_type = 't' check_metric_tensor(g) # The definition of the start index if isinstance(g, Matrix): idx_st = 0 else: idx_st = g.start_index[0] # The start index is the same if isinstance(g, type(args)) and idx_st != idx_args: raise ValueError( "The start index of the metric tensor and vector of arguments \ must be equal") if isinstance(g, (TensorArray, Arraypy)): g = g.to_matrix() # 2.if g is NULL else: # g - the identity matrix g = eye(len(args)) idx_st = 0 # Creating the output array in accordance with start indexes n = len(args) array = Arraypy([1, n, idx_st]) indices = range(idx_st, idx_st + n) # Calculating g_inv = g.inv() if isinstance(args, (TensorArray, Arraypy)): args = args.to_list() for i in indices: for j in indices: array[i] += (g_inv[i - idx_st, j - idx_st] * diff(f, args[j - idx_st])) # Handling of an output array if output_type == 't' or output_type == Symbol('t'): gradient = Arraypy.to_tensor(array, 1) elif output_type == 'a' or output_type == Symbol('a'): gradient = array elif output_type == 'l' or output_type == Symbol('l') or output_type is \ None: gradient = Arraypy.to_list(array) else: raise TypeError( "The third argument must be 't' - tensor,'a' - Arraypy, \ 'l' - list") # Output return gradient
def _eval_expand_diracdelta(self, **hints): """Compute a simplified representation of the function using property number 4. Pass wrt as a hint to expand the expression with respect to a particular variable. wrt is: - a variable with respect to which a DiracDelta expression will get expanded. Examples ======== >>> from sympy import DiracDelta >>> from sympy.abc import x, y >>> DiracDelta(x*y).expand(diracdelta=True, wrt=x) DiracDelta(x)/Abs(y) >>> DiracDelta(x*y).expand(diracdelta=True, wrt=y) DiracDelta(y)/Abs(x) >>> DiracDelta(x**2 + x - 2).expand(diracdelta=True, wrt=x) DiracDelta(x - 1)/3 + DiracDelta(x + 2)/3 See Also ======== is_simple, Diracdelta """ from sympy.polys.polyroots import roots wrt = hints.get('wrt', None) if wrt is None: free = self.free_symbols if len(free) == 1: wrt = free.pop() else: raise TypeError(filldedent(''' When there is more than 1 free symbol or variable in the expression, the 'wrt' keyword is required as a hint to expand when using the DiracDelta hint.''')) if not self.args[0].has(wrt) or (len(self.args) > 1 and self.args[1] != 0 ): return self try: argroots = roots(self.args[0], wrt) result = 0 valid = True darg = abs(diff(self.args[0], wrt)) for r, m in argroots.items(): if r.is_real is not False and m == 1: result += self.func(wrt - r)/darg.subs(wrt, r) else: # don't handle non-real and if m != 1 then # a polynomial will have a zero in the derivative (darg) # at r valid = False break if valid: return result except PolynomialError: pass return self
def covar_der(X, g, var, type_output='t'): """Return the covariant derivative the vector field. Examples: ========= >>> from sympy.tensor.riemannian_geometry import covar_der >>> from sympy.tensor.arraypy import Arraypy, TensorArray >>> from sympy import symbols, cos >>> x1, x2 = symbols('x1, x2') var it's a list of symbolic arguments. May be a list, one-dimensional arraypy or one-dimensional tensor with valence of indices (+1): >>> var = [x1, x2] g it's a metric tensor must be symmetric matrix, arraypy or tensor with valence indices (-1, -1): >>> A = Arraypy((2, 2)) >>> g = TensorArray(A,(-1, -1)) >>> g[0,0] = cos(x2)**2 >>> g[0,1] = 0 >>> g[1,0] = 0 >>> g[1,1] = 1 X it's vector field can be a list, one-dimensional arraypy, or one-dimensional tensor with valences of indices (+1): >>> X = [x1 * x2**3, x1 - cos(x2)] type_output it's optional parameter function, indicating the type of calculation result and receiving the character or string value: - symbol 't' means that the type of the result will match TensorArray; - symbol 'a' means that the type of the result will be Arraypy; - default function takes a parameter 't', so that the result will be a TensorArray. The covariant derivative: >>> c_v = covar_der(X, g, var, 't') >>> print(c_v) x2**3 - (x1 - cos(x2))*sin(x2)/cos(x2) x1*x2**3*sin(x2)*cos(x2) + 1 -x1*x2**3*sin(x2)/cos(x2) + 3*x1*x2**2 sin(x2) >>> c_v.type_pq (1, 1) """ # Handling of input vector of arguments - var if not isinstance(var, (list, Arraypy, TensorArray)): raise TypeError( 'The type of vector of arguments must be a list, Arraypy or TensorArray') if isinstance(var, (TensorArray, Arraypy)): if len(var.shape) != 1: raise ValueError("The dimension of vector of arguments must be 1") if isinstance(var, TensorArray): if not var.type_pq == (1, 0): raise ValueError( 'The valence of vector of arguments must be (+1)') if isinstance(var, (TensorArray, Arraypy)): var = var.to_list() # Definition of number of variables n = len(var) # Handling of a input argument - metric tensor g if not isinstance(g, (Matrix, Arraypy, TensorArray)): raise TypeError( 'The type of metric tensor must be Matrix, TensorArray or Arraypy') else: if isinstance(g, (Arraypy, TensorArray)): if isinstance(g, TensorArray): if not g.type_pq == (0, 2): raise ValueError( 'The valence of metric tensor must be (-1,-1)') if not is_symmetric(g): raise ValueError('The metric tensor must be symmetric.') if not (g.start_index[0] == g.start_index[1]): raise ValueError( 'The starting indices of metric tensor must be identical') idx_g = g.start_index[0] elif isinstance(g, Matrix): if not g.is_symmetric(): raise ValueError('The metric tensor must be symmetric.') idx_g = 0 # Handling of a input argument - vector field X if not isinstance(X, (list, Arraypy, TensorArray)): raise TypeError( 'The type of vector field must be list, TensorArray or Arraypy') else: if isinstance(X, (Arraypy, TensorArray)): if len(X.shape) != 1: raise ValueError("The dimension of vector field must be 1") if isinstance(X, TensorArray): if not X.type_pq == (1, 0): raise ValueError( 'The valence of vector field must be (+1)') idx_X = X.start_index[0] elif isinstance(X, list): idx_X = 0 # The definition of diapason changes in an index [n1, n2] = g.shape if not n == n1: raise ValueError( 'The rank of the metric tensor does not coincide with the number of variables.') if (idx_g != idx_X): raise ValueError( 'The start index of the metric tensor and vector field must be equal') else: idx_start = idx_g indices = range(idx_start, idx_start + n) # Creating of output array with new indices cov = Arraypy([2, n, idx_start]) ch_2 = christoffel_2(g, var) # Calculation for i in indices: for j in indices: cov[i, j] = diff(X[j], var[i - idx_start]) + \ Add(*[ch_2[k, i, j] * X[k] for k in indices]) # Handling of an output array if type_output == str('t') or type_output == Symbol('t'): cov_der = cov.to_tensor((1, -1)) elif type_output == str('a') or type_output == Symbol('a'): cov_der = cov else: raise ValueError( "The parameter of type output result must 'a' - Arraypy or 't' and None - TensorArray.") # Output return cov_der
def _eval_derivative(self, s): return Piecewise(*[(diff(e, s), c) for e, c in self.args])
def df(f, args, output_type='l'): """Return an the 1-form df, differential of function f. Examples: ========= >>> from tensor_analysis.tensor_fields import df >>> from sympy import symbols, sin >>> from tensor_analysis.arraypy import Arraypy >>> x1, x2, x3= symbols('x1 x2 x3') f it's a function the differential of that is calculated: >>> f=x1**2*x2 + sin(x2*x3 - x2) args it's a list of symbol arguments of the function f. It can be in list, array of arraypy or contravariant tensor: >>> args_t=Arraypy([1,3,1]).to_tensor(1) >>> args_t[1]=x1 >>> args_t[2]=x2 >>> args_t[3]=x3 output_type it is an optional parameter accepting symbol value of 'l', 'a' or 't' and indicative on the type of result of calculations: - 'l' it is a result as a list(list); - 'a' it is a result as an unidimensional array of arraypy; - 't' it is a result as an unidimensional covariant tensor. Differential: >>> d = df(f, args_t, 't') >>> print(d) 2*x1*x2 x1**2 + (x3 - 1)*cos(x2*x3 - x2) x2*cos(x2*x3 - x2) The valence of the returned tensor: >>> d.type_pq (0, 1) """ # Handling of a vector of arguments check_vector_of_arguments(args) # The definition of the start index if isinstance(args, list): idx_start = 0 else: idx_start = args.start_index[0] # Creating the output array in accordance with the start index n = len(args) array = Arraypy([1, n, idx_start]) # Calculation for k in range(idx_start, idx_start + n): array[k] = diff(f, args[k]) # Handling of an output array if output_type == 't' or output_type == Symbol('t'): differential = Arraypy.to_tensor(array, -1) elif output_type == 'a' or output_type == Symbol('a'): differential = array elif output_type == 'l' or output_type == Symbol('l'): differential = Arraypy.to_list(array) else: raise TypeError( "The third argument must be 't' - TensorArray,'a' - Arraypy, \ 'l' - list") # Output return differential
def riemann(g, var, type_output='t'): """Return the Riemann curvature tensor of type (1, -1, -1, -1) for the given metric tensor. Examples: ========= >>> from sympy.tensor.riemannian_geometry import riemann >>> from sympy.tensor.arraypy import Arraypy, TensorArray >>> from sympy import symbols, cos >>> x1, x2 = symbols('x1, x2') var it's a list of symbolic arguments. May be a list, one-dimensional arraypy or one-dimensional tensor with valence of indices (+1): >>> var = [x1, x2] g it's a metric tensor must be symmetric matrix, arraypy or tensor with valence indices (-1, -1): >>> A = Arraypy((2, 2)) >>> g = TensorArray(A,(-1, -1)) >>> g[0,0] = cos(x2)**2 >>> g[0,1] = 0 >>> g[1,0] = 0 >>> g[1,1] = 1 type_output it's optional parameter function, indicating the type of calculation result and receiving the character or string value: - symbol 't' means that the type of the result will match TensorArray; - symbol 'a' means that the type of the result will be Arraypy; - default function takes a parameter 't', so that the result will be a TensorArray. The curvature tensor: >>> r = riemann(g, var, 'a') >>> print(r) 0 0 0 0 0 -cos(x2)**2 1 0 0 cos(x2)**2 -1 0 0 0 0 0 """ # Handling of input vector of arguments - var if not isinstance(var, (list, Arraypy, TensorArray)): raise TypeError( 'The type of vector of arguments must be a list, Arraypy or TensorArray') if isinstance(var, (TensorArray, Arraypy)): if len(var.shape) != 1: raise ValueError("The dimension of vector of arguments must be 1") if isinstance(var, TensorArray): if not var.type_pq == (1, 0): raise ValueError( 'The valence of vector of arguments must be (+1)') if isinstance(var, (TensorArray, Arraypy)): var = var.to_list() # Definition of number of variables n = len(var) # Handling of a input argument - metric tensor g if not isinstance(g, (Matrix, Arraypy, TensorArray)): raise TypeError( 'The type of metric tensor must be Matrix, TensorArray or Arraypy') else: if isinstance(g, (Arraypy, TensorArray)): if isinstance(g, TensorArray): if not g.type_pq == (0, 2): raise ValueError( 'The valence of metric tensor must be (-1,-1)') if not is_symmetric(g): raise ValueError('The metric tensor must be symmetric.') if not (g.start_index[0] == g.start_index[1]): raise ValueError( 'The starting indices of metric tensor must be identical') idx_start = g.start_index[0] elif isinstance(g, Matrix): if not g.is_symmetric(): raise ValueError('The metric tensor must be symmetric.') idx_start = 0 # The definition of diapason changes in an index [n1, n2] = g.shape if not n == n1: raise ValueError( 'The rank of the metric tensor does not coincide with the number of variables.') indices = range(idx_start, idx_start + n) # Creating of output array with new indices R = Arraypy([4, n, idx_start]) ch_2 = christoffel_2(g, var) # Calculation for i in indices: for j in indices: for k in indices: for l in indices: R[i, j, k, l] = diff(ch_2[j, k, l], var[i - idx_start]) - diff(ch_2[i, k, l], var[j - idx_start]) + sum([ch_2[i, p, l] * ch_2[j, k, p] - ch_2[j, p, l] * ch_2[i, k, p] for p in indices]) # Handling of an output array if type_output == str('t') or type_output == Symbol('t'): riemann = R.to_tensor((1, -1, -1, -1)) elif type_output == str('a') or type_output == Symbol('a'): riemann = R else: raise ValueError( "The parameter of type output result must 'a' - Arraypy or 't' and None - TensorArray.") # Output return riemann
def _eval_derivative(self, sym): """Evaluate the derivative of the current Integral object by differentiating under the integral sign [1], using the Fundamental Theorem of Calculus [2] when possible. Whenever an Integral is encountered that is equivalent to zero or has an integrand that is independent of the variable of integration those integrals are performed. All others are returned as Integral instances which can be resolved with doit() (provided they are integrable). References: [1] http://en.wikipedia.org/wiki/Differentiation_under_the_integral_sign [2] http://en.wikipedia.org/wiki/Fundamental_theorem_of_calculus >>> from sympy import Integral >>> from sympy.abc import x, y >>> i = Integral(x + y, y, (y, 1, x)) >>> i.diff(x) Integral(x + y, (y, x)) + Integral(1, (y, y), (y, 1, x)) >>> i.doit().diff(x) == i.diff(x).doit() True >>> i.diff(y) 0 The previous must be true since there is no y in the evaluated integral: >>> i.free_symbols set([x]) >>> i.doit() 2*x**3/3 - x/2 - 1/6 """ # differentiate under the integral sign; we do not # check for regularity conditions (TODO), see issue 1116 # get limits and the function f, limits = self.function, list(self.limits) # the order matters if variables of integration appear in the limits # so work our way in from the outside to the inside. limit = limits.pop(-1) if len(limit) == 3: x, a, b = limit elif len(limit) == 2: x, b = limit a = None else: a = b = None x = limit[0] if limits: # f is the argument to an integral f = Integral(f, *tuple(limits)) # assemble the pieces rv = 0 if b is not None: rv += f.subs(x, b)*diff(b, sym) if a is not None: rv -= f.subs(x, a)*diff(a, sym) if len(limit) == 1 and sym == x: # the dummy variable *is* also the real-world variable arg = f rv += arg else: # the dummy variable might match sym but it's # only a dummy and the actual variable is determined # by the limits, so mask off the variable of integration # while differentiating u = Dummy('u') arg = f.subs(x, u).diff(sym).subs(u, x) rv += Integral(arg, Tuple(x, a, b)) return rv
def _eval_derivative(self, x): return self.func(*[(diff(e, x), c) for e, c in self.args])
def diverg(X, args, g=None): """Return the divergence of a vector field X. Compute divergence of vector field consisting of N elements. Examples: ========= >>> from tensor_analysis.tensor_fields import diverg >>> from sympy import symbols, cos >>> from sympy.matrices import Matrix >>> x1, x2, x3 = symbols('x1 x2 x3') X is a vector field, args it's a list of symbol arguments of the vector field X. It's can be in list, array of arraypy or contravariant tensor: >>> X = [x1*x2**3,x2-cos(x3),x3**3-x1] >>> arg = [x1, x2, x3] g - optional parameter, metric tensor, which can be a matrix "Matrix", array of arraypy or covariant tensor: >>> g = Matrix([[2,1,0],[1,3,0],[0,0,1]]) >>> dv = diverg(X,arg,g) >>> print(dv) x2**3 + 3*x3**2 + 1 """ # Handling of a vector of arguments check_vector_of_arguments(args) if isinstance(args, list): idx_args = 0 else: idx_args = args.start_index[0] # Handling of the first vector field check_the_vector_field(X) if isinstance(X, (TensorArray, Arraypy)): idx_X = X.start_index[0] else: idx_X = 0 if idx_args != idx_X: raise ValueError( "The start index of vector field and vector of arguments must be \ equal") # Handling of the metric tensor if g is not None: if isinstance(g, (TensorArray, Arraypy)): g = g.to_matrix() else: g = eye(len(args)) # Calculation sq = sqrt(abs(det(g))) diver = 0 for k in range(len(args)): diver += simplify(1 / sq * sum([diff(X[k + idx_X] * sq, args[k + idx_X])])) # Output return diver
def curl(X, args, output_type=None): """Return the rotor vector field curl(X) of a vector field X in R^3 (curl, rotation, rotor, vorticity). A rotor can be calculated for only in three-dimensional Euclidean space. Examples: ========= >>> from tensor_analysis.tensor_fields import curl >>> from sympy import symbols, cos >>> from tensor_analysis.arraypy import Arraypy, TensorArray >>> x1, x2, x3 = symbols('x1 x2 x3') X is a vector field, args it's a list of symbol arguments of a vector field X. They can be a list, array arraypy or contravariant tensor: >>> X=Arraypy(3) >>> X_t=TensorArray(X,(1)) >>> X_t[0]=x1*x2**3 >>> X_t[1]=x2-cos(x3) >>> X_t[2]=x3**3-x1 >>> arg=[x1,x2,x3] >>> r=curl(X_t,arg,'t') >>> print(r) -sin(x3) 1 -3*x1*x2**2 >>> r.type_pq (1, 0) """ # Handling of a vector of arguments check_vector_of_arguments(args) if len(args) != 3: raise ValueError("Three variables are required") # The definition of the start index if isinstance(args, list): idx_args = 0 else: idx_args = args.start_index[0] # Handling of a vector field check_the_vector_field(X) if len(X) != 3: raise ValueError("A three-dimensional vector field is necessary") # The definition of the start index and type of output if isinstance(X, (TensorArray, Arraypy)): if isinstance(X, TensorArray): out_t = 't' idx_X = X.start_index[0] else: idx_X = 0 out_t = 'l' # The definition type of output of an output array if output_type is None: if out_t is not None: output_type = out_t else: output_type = 'a' # The definition of the start index if isinstance(X, type(args)) and (idx_X != idx_args): raise ValueError( "The start index of vector field and vector of arguments must be \ equal") idx_st = idx_X # Creating the output array in accordance with the start index array = Arraypy([1, 3, idx_st]) # Calculation if isinstance(X, (TensorArray, Arraypy)): X = X.to_list() if isinstance(args, (TensorArray, Arraypy)): args = args.to_list() array[idx_st] = (diff(X[2], args[1]) - diff(X[1], args[2])) array[idx_st + 1] = diff(X[0], args[2]) - diff(X[2], args[0]) array[idx_st + 2] = diff(X[1], args[0]) - diff(X[0], args[1]) # Handling of an output array if output_type == 't' or output_type == Symbol('t'): rotor = Arraypy.to_tensor(array, 1) elif output_type == 'a' or output_type == Symbol('a'): rotor = array elif output_type == 'l' or output_type == Symbol('l'): rotor = Arraypy.to_list(array) else: raise TypeError( "The third argument must be 't'-tensor,'a'-Arraypy, \ 'l'-list") # Output return rotor
def der_one(a): return diff(f, x).subs(x, a)
def lie_w(omega, X, args): """Return a skew-symmetric tensor of type (0,p). Function lie_w calculates all the components of the Lie derivative differential forms in a symbolic form. Indexes the output tensor will start as well as the input tensor (array) "omega". If all the input parameters of the same type, they must be equal to the initial indexes. Examples: ========= >>> from tensor_analysis.tensor_fields import lie_w >>> from sympy import symbols, cos >>> from tensor_analysis.arraypy import Arraypy >>> x1, x2, x3 = symbols('x1 x2 x3') omega - skew-symmetric tensor. Can be a tensor of type (0,p) or an array arraypy: >>> omega=Arraypy([2,3,1]).to_tensor((-1,-1)) >>> omega[1,2]=x3 >>> omega[1,3]=-x2 >>> omega[2,1]=-x3 >>> omega[2,3]=x1 >>> omega[3,1]=x2 >>> omega[3,2]=-x1 X - the vector field along which the derivative is calculated: >>> X = [x1*x2**3,x2-cos(x3),x3**3-x1] args it's a list of symbol arguments. It's can be in list, array of arraypy or contravariant tensor: >>> arg = [x1, x2, x3] Lie derivative of a differential form: >>> li = lie_w(omega,X,arg) >>> print(li) 0 x2**3*x3 + x3**3 + x3 -x2**4 - 3*x2*x3**2 - x2 + x3*sin(x3) + cos(x3) -x2**3*x3 - x3**3 - x3 0 -2*x1*x2**3 + 3*x1*x3**2 + x1 x2**4 + 3*x2*x3**2 + x2 - x3*sin(x3) - cos(x3) 2*x1*x2**3 - 3*x1*x3**2 - x1 0 >>> li.type_pq (0, 2) """ # Handling of a vector of arguments check_vector_of_arguments(args) if isinstance(args, list): idx_args = 0 else: idx_args = args.start_index[0] # Handling of a vector field check_the_vector_field(X) if isinstance(X, (TensorArray, Arraypy)): idx_X = X.start_index[0] else: idx_X = 0 # Handling of a differential form if not isinstance(omega, (TensorArray, Arraypy)): raise ValueError( "The type of differential form must be TensorArray or Arraypy") if not is_asymmetric(omega): raise ValueError("The differential form must be a skew-symmetric") idx_omega = omega.start_index[0] # Define the start index in the output tensor if type(omega) == type(X) == type(args): if idx_omega != idx_X or idx_omega != idx_args or idx_X != idx_args: raise ValueError( "The start index of differential form, vector field and \ vector of argements must be equal") if isinstance(omega, type(X)) and idx_omega != idx_X: raise ValueError( "The start index of differential form and vector field must be \ equal") idx_st = idx_omega # Creating the output array in accordance with start indexes n = omega.shape[0] # the dimensionality of the input array r = len(omega.shape) # the rank of the input array a = Arraypy([r, n, idx_st]) valence_list = [(-1) for k in range(r)] diff_Lie = a.to_tensor(valence_list) # Calculation idx = diff_Lie.start_index if isinstance(args, (TensorArray, Arraypy)): args = args.to_list() if isinstance(X, (TensorArray, Arraypy)): X = X.to_list() l_idx = len(idx) for p in range(len(diff_Lie)): for k in range(l_idx + 1): tuple_list_indx = [ replace_index_to_k(idx, f, k + idx_st) for f in range(l_idx)] # the intermediate value diff_omega = diff(omega[idx], args[k]) * X[k] for j in range(l_idx): diff_Lie[idx] += diff(X[k], args[idx[j] - idx_st]) *\ omega[tuple_list_indx[j]] diff_Lie[idx] = diff_Lie[idx] + diff_omega idx = diff_Lie.next_index(idx) # Output return diff_Lie
def dw(omega, args): """Return a skew-symmetric tensor of type (0, p+1). Indexes the output tensor will start as well as the input tensor (array). If the input parameters of the same type, they must be equal to the initial indexes. Examples: ========= >>> from tensor_analysis.tensor_fields import dw >>> from sympy import symbols >>> from tensor_analysis.arraypy import Arraypy >>> x1, x2, x3 = symbols('x1 x2 x3') omega - differential form, differential which is calculated. It's can be a skew-symmetric tensor of type (0,p) or an array arraypy: >>> omega=Arraypy([2,3,1]).to_tensor((-1,-1)) >>> omega[1,2]=x3 >>> omega[1,3]=-x2 >>> omega[2,1]=-x3 >>> omega[2,3]=x1 >>> omega[3,1]=x2 >>> omega[3,2]=-x1 args it's a list of symbol arguments of differential form. It's can be in list, array of arraypy or contravariant tensor. External differential of a differential forms: >>> domega=dw(omega, [x1,x2,x3]) >>> print(domega) 0 0 0 0 0 3 0 -3 0 0 0 -3 0 0 0 3 0 0 0 3 0 -3 0 0 0 0 0 >>> domega.type_pq (0, 3) """ # Handling of a vector of arguments check_vector_of_arguments(args) # The definition of the start index of args if isinstance(args, list): idx_args = 0 else: idx_args = args.start_index[0] # Handling of a differential form if not isinstance(omega, (TensorArray, Arraypy)): raise ValueError( "The type of differential form must be TensorArray or Arraypy") if omega.rank > 1: if not is_asymmetric(omega): raise ValueError("The differential form must be a skew-symmetric") idx_omega = omega.start_index[0] # Define the start index in the output tensor if isinstance(omega, type(args)) and idx_omega != idx_args: raise ValueError("The start index of the differential form and \ vector of arguments must be equal") idx_st = idx_omega # Creating the output array in accordance with start indexes n = omega.shape[0] # the dimensionality of the input array p = len(omega.shape) # the rank of the input array valence_ind = [(-1) for k in range(p + 1)] d_omega = Arraypy([p + 1, n, idx_st]).to_tensor(valence_ind) # Calculation idx = d_omega.start_index if isinstance(args, (TensorArray, Arraypy)): args = args.to_list() for i in range(len(d_omega)): # tuple_list_indx it's list of tuple. Example:[(0, 1), (0, 1), (0, 0)] tuple_list_indx = [ delete_index_from_list( idx, f) for f in range( len(idx))] for k in range(p + 1): d_omega[idx] += Add(((-1)**k) * diff(omega[tuple_list_indx[k]], args[idx[k] - idx_st])) idx = d_omega.next_index(idx) # Output return d_omega
def _eval_derivative(self, sym): """Evaluate the derivative of the current Integral object by differentiating under the integral sign [1], using the Fundamental Theorem of Calculus [2] when possible. Whenever an Integral is encountered that is equivalent to zero or has an integrand that is independent of the variable of integration those integrals are performed. All others are returned as Integral instances which can be resolved with doit() (provided they are integrable). References: [1] http://en.wikipedia.org/wiki/Differentiation_under_the_integral_sign [2] http://en.wikipedia.org/wiki/Fundamental_theorem_of_calculus >>> from sympy import Integral >>> from sympy.abc import x, y >>> i = Integral(x + y, y, (y, 1, x)) >>> i.diff(x) Integral(x + y, (y, x)) + Integral(1, (y, y), (y, 1, x)) >>> i.doit().diff(x) == i.diff(x).doit() True >>> i.diff(y) 0 The previous must be true since there is no y in the evaluated integral: >>> i.free_symbols set([x]) >>> i.doit() -1/6 - x/2 + 2*x**3/3 """ # differentiate under the integral sign; we do not # check for regularity conditions (TODO), see issue 1116 # get limits and the function f, limits = self.function, list(self.limits) # the order matters if variables of integration appear in the limits # so work our way in from the outside to the inside. limit = limits.pop(-1) if len(limit) == 3: x, a, b = limit elif len(limit) == 2: x, b = limit a = None else: a = b = None x = limit[0] if limits: # f is the argument to an integral f = Integral(f, *tuple(limits)) # assemble the pieces rv = 0 if b is not None: rv += f.subs(x, b)*diff(b, sym) if a is not None: rv -= f.subs(x, a)*diff(a, sym) if len(limit) == 1 and sym == x: # the dummy variable *is* also the real-world variable arg = f rv += arg else: # the dummy variable might match sym but it's # only a dummy and the actual variable is determined # by the limits, so mask off the variable of integration # while differentiating u = Dummy('u') arg = f.subs(x, u).diff(sym).subs(u, x) rv += Integral(arg, Tuple(x, a, b)) return rv
def der_two(a): return diff(diff(f, x)).subs(x, a)
def _eval_expand_diracdelta(self, **hints): """ Compute a simplified representation of the function using property number 4. Pass ``wrt`` as a hint to expand the expression with respect to a particular variable. Explanation =========== ``wrt`` is: - a variable with respect to which a DiracDelta expression will get expanded. Examples ======== >>> from sympy import DiracDelta >>> from sympy.abc import x, y >>> DiracDelta(x*y).expand(diracdelta=True, wrt=x) DiracDelta(x)/Abs(y) >>> DiracDelta(x*y).expand(diracdelta=True, wrt=y) DiracDelta(y)/Abs(x) >>> DiracDelta(x**2 + x - 2).expand(diracdelta=True, wrt=x) DiracDelta(x - 1)/3 + DiracDelta(x + 2)/3 See Also ======== is_simple, Diracdelta """ from sympy.polys.polyroots import roots wrt = hints.get('wrt', None) if wrt is None: free = self.free_symbols if len(free) == 1: wrt = free.pop() else: raise TypeError(filldedent(''' When there is more than 1 free symbol or variable in the expression, the 'wrt' keyword is required as a hint to expand when using the DiracDelta hint.''')) if not self.args[0].has(wrt) or (len(self.args) > 1 and self.args[1] != 0 ): return self try: argroots = roots(self.args[0], wrt) result = 0 valid = True darg = abs(diff(self.args[0], wrt)) for r, m in argroots.items(): if r.is_real is not False and m == 1: result += self.func(wrt - r)/darg.subs(wrt, r) else: # don't handle non-real and if m != 1 then # a polynomial will have a zero in the derivative (darg) # at r valid = False break if valid: return result except PolynomialError: pass return self
def _eval_derivative(self, x): return Piecewise(*[(diff(e, x), c) for e, c in self.args])
def lie_xy(X, Y, args, output_type=None): """Return the vector field [X,Y], Lie bracket (commutator) of a vector fields X and Y. Examples: ========= >>> from tensor_analysis.tensor_fields import lie_xy >>> from sympy import symbols, cos, sin >>> x1, x2, x3 = symbols('x1 x2 x3') X, Y is a vector field, args it's a list of symbol arguments. It's can be a list, array arraypy or contravariant tensor: >>> X=[x1*x2**3,x2-cos(x3),x3**3-x1] >>> Y = [x1**3*x2**3, x2*x3 - sin(x1*x3), x3**3 - x1**2] >>> arg = [x1, x2, x3] The Lie brackets of two vector fields: >>> lie = lie_xy(X, Y, arg,'a') >>> print(lie) 2*x1**3*x2**6 + 3*x1**3*x2**2*(x2 - cos(x3)) - 3*x1*x2**2*(x2*x3 - \ sin(x1*x3)) -x1*x2**3*x3*cos(x1*x3) - x2*x3 + x3*(x2 - cos(x3)) + \ (-x1 + x3**3)*(-x1*cos(x1*x3) + x2) - (-x1**2 + x3**3)*sin(x3) + sin(x1*x3) x1**3*x2**3 - 2*x1**2*x2**3 + 3*x3**2*(-x1 + x3**3) - \ 3*x3**2*(-x1**2 + x3**3) """ # Handling of a vector of arguments check_vector_of_arguments(args) # The definition of the start index args if isinstance(args, list): idx_args = 0 else: idx_args = args.start_index[0] # Handling of the first vector field check_the_vector_field(X) # The definition of the start index X and type of output if isinstance(X, (TensorArray, Arraypy)): if isinstance(X, TensorArray): out_t = 't' idx_X = X.start_index[0] else: idx_X = 0 out_t = 'l' # Handling of the second vector field check_the_vector_field(Y) # The definition of the start index Y if isinstance(Y, (TensorArray, Arraypy)): idx_Y = Y.start_index[0] else: idx_Y = 0 if len(Y) != len(X): raise ValueError( "The different number of arguments in the vector fields") elif len(args) != len(X) or len(args) != len(Y): raise ValueError( "The different number of components in the vector field and \ vector of arguments") # Define the start index in the output tensor if type(Y) == type(X) == type(args): if idx_Y != idx_X or idx_Y != idx_args or idx_X != idx_args: raise ValueError( "The start index of vector fields and vector of argements \ must be equal") if idx_Y != idx_X: raise ValueError( "The start index of vector fields must be equal") idx_st = idx_Y if output_type is None: if out_t is not None: output_type = out_t else: output_type = 'a' # Creating the output array in accordance with start indexes Li = Arraypy([1, len(X), idx_st]) # Calculating if isinstance(Y, (TensorArray, Arraypy)): Y = Y.to_list() if isinstance(X, (TensorArray, Arraypy)): X = X.to_list() if isinstance(args, (TensorArray, Arraypy)): args = args.to_list() if X == Y: return 0 else: indices = range(len(args)) for i in indices: for k in indices: Li[i + idx_st] += Add(diff(Y[i], args[k]) * X[k] - diff(X[i], args[k]) * Y[k]) # Handling of an output array if output_type == 't' or output_type == Symbol('t'): Lie = Arraypy.to_tensor(Li, 1) elif output_type == 'a' or output_type == Symbol('a'): Lie = Li elif output_type == 'l' or output_type == Symbol('l'): Lie = Arraypy.to_list(Li) else: raise TypeError( "The third argument must be 't'-TensorArray,'a'-Arraypy, \ 'l'-list") # Output return Lie
def __new__(cls, field, parametricregion): coord_set = _get_coord_systems(field) if len(coord_set) == 0: coord_sys = CoordSys3D('C') elif len(coord_set) > 1: raise ValueError else: coord_sys = next(iter(coord_set)) if parametricregion.dimensions == 0: return S.Zero base_vectors = coord_sys.base_vectors() base_scalars = coord_sys.base_scalars() parametricfield = field r = Vector.zero for i in range(len(parametricregion.definition)): r += base_vectors[i] * parametricregion.definition[i] if len(coord_set) != 0: for i in range(len(parametricregion.definition)): parametricfield = parametricfield.subs( base_scalars[i], parametricregion.definition[i]) if parametricregion.dimensions == 1: parameter = parametricregion.parameters[0] r_diff = diff(r, parameter) lower, upper = parametricregion.limits[parameter][ 0], parametricregion.limits[parameter][1] if isinstance(parametricfield, Vector): integrand = simplify(r_diff.dot(parametricfield)) else: integrand = simplify(r_diff.magnitude() * parametricfield) result = integrate(integrand, (parameter, lower, upper)) elif parametricregion.dimensions == 2: u, v = cls._bounds_case(parametricregion.parameters, parametricregion.limits) r_u = diff(r, u) r_v = diff(r, v) normal_vector = simplify(r_u.cross(r_v)) if isinstance(parametricfield, Vector): integrand = parametricfield.dot(normal_vector) else: integrand = parametricfield * normal_vector.magnitude() integrand = simplify(integrand) lower_u, upper_u = parametricregion.limits[u][ 0], parametricregion.limits[u][1] lower_v, upper_v = parametricregion.limits[v][ 0], parametricregion.limits[v][1] result = integrate(integrand, (u, lower_u, upper_u), (v, lower_v, upper_v)) else: variables = cls._bounds_case(parametricregion.parameters, parametricregion.limits) coeff = Matrix( parametricregion.definition).jacobian(variables).det() integrand = simplify(parametricfield * coeff) l = [(var, parametricregion.limits[var][0], parametricregion.limits[var][1]) for var in variables] result = integrate(integrand, *l) if not isinstance(result, Integral): return result else: return super().__new__(cls, field, parametricregion)
def der_three(a): return diff(diff(diff(f, x))).subs(x, a)