def get_leg_position(front=True, left=True): anchor = Translate(body_width / 2, body_width / 2, 0) if not left: anchor = ReflectX() @ anchor if not front: anchor = ReflectY() @ anchor atoms = sp.symbols(r'w_b, w_r, w_h, u_b, u_r, u_h') rot_from_pivot, rot_y_from_z, rot_d_from_z, u_a, u_r, u_h = atoms chain = get_active_kinematic_chain(rot_from_pivot, rot_y_from_z, rot_d_from_z) Leg_Bottom = anchor @ chain[-1] @ origin foot_pos = [] f_a = get_body_linkage_constraint(rot_from_pivot, u_a) f_t = get_leg_top_constraint(rot_y_from_z, u_r) f_b = get_leg_bottom_constraint(rot_d_from_z, u_h) for i in range(0, 3): foot_pos.append( filter_tiny_numbers(sp.expand_trig(sp.simplify(Leg_Bottom[i])))) constraints = [ 2 * sp.expand_trig(sp.simplify(sp.expand(f))) for f in (f_a, f_t, f_b) ] return atoms, foot_pos, constraints
def _get_Ylm(self, l, m): """ Compute an expression for spherical harmonic of order (l,m) in terms of Cartesian unit vectors, :math:`\hat{z}` and :math:`\hat{x} + i \hat{y}` Parameters ---------- l : int the degree of the harmonic m : int the order of the harmonic; |m| < l Returns ------- expr : a sympy expression that corresponds to the requested Ylm References ---------- https://en.wikipedia.org/wiki/Spherical_harmonics """ import sympy as sp # the relevant cartesian and spherical symbols x, y, z, r = sp.symbols('x y z r', real=True, positive=True) xhat, yhat, zhat = sp.symbols('xhat yhat zhat', real=True, positive=True) xpyhat = sp.Symbol('xpyhat', complex=True) phi, theta = sp.symbols('phi theta') defs = [(sp.sin(phi), y / sp.sqrt(x**2 + y**2)), (sp.cos(phi), x / sp.sqrt(x**2 + y**2)), (sp.cos(theta), z / sp.sqrt(x**2 + y**2 + z**2))] # the cos(theta) dependence encoded by the associated Legendre poly expr = sp.assoc_legendre(l, m, sp.cos(theta)) # the exp(i*m*phi) dependence expr *= sp.expand_trig(sp.cos( m * phi)) + sp.I * sp.expand_trig(sp.sin(m * phi)) # simplifying optimizations expr = sp.together(expr.subs(defs)).subs(x**2 + y**2 + z**2, r**2) expr = expr.expand().subs([(x / r, xhat), (y / r, yhat), (z / r, zhat)]) expr = expr.factor().factor(extension=[sp.I]).subs( xhat + sp.I * yhat, xpyhat) expr = expr.subs(xhat**2 + yhat**2, 1 - zhat**2).factor() # and finally add the normalization amp = sp.sqrt((2 * l + 1) / (4 * numpy.pi) * sp.factorial(l - m) / sp.factorial(l + m)) expr *= amp return expr
def substitute_trig(l1x,l1y,l2x,l2y,l1,l2): phi1 = Symbol('phi1') phi2 = Symbol('phi2') cos2t12 = sympy.cos(2*(phi1-phi2)) sin2t12 = sympy.sin(2*(phi1-phi2)) simpcos = sympy.expand_trig(cos2t12) simpsin = sympy.expand_trig(sin2t12) cos2t12 = sympy.expand(sympy.simplify(simpcos.subs([(sympy.cos(phi1),l1x/l1),(sympy.cos(phi2),l2x/l2), (sympy.sin(phi1),l1y/l1),(sympy.sin(phi2),l2y/l2)]))) sin2t12 = sympy.expand(sympy.simplify(simpsin.subs([(sympy.cos(phi1),l1x/l1),(sympy.cos(phi2),l2x/l2), (sympy.sin(phi1),l1y/l1),(sympy.sin(phi2),l2y/l2)]))) return cos2t12,sin2t12
def _get_Ylm(self, l, m): """ Compute an expression for spherical harmonic of order (l,m) in terms of Cartesian unit vectors, :math:`\hat{z}` and :math:`\hat{x} + i \hat{y}` Parameters ---------- l : int the degree of the harmonic m : int the order of the harmonic; |m| < l Returns ------- expr : a sympy expression that corresponds to the requested Ylm References ---------- https://en.wikipedia.org/wiki/Spherical_harmonics """ import sympy as sp # the relevant cartesian and spherical symbols x, y, z, r = sp.symbols('x y z r', real=True, positive=True) xhat, yhat, zhat = sp.symbols('xhat yhat zhat', real=True, positive=True) xpyhat = sp.Symbol('xpyhat', complex=True) phi, theta = sp.symbols('phi theta') defs = [(sp.sin(phi), y/sp.sqrt(x**2+y**2)), (sp.cos(phi), x/sp.sqrt(x**2+y**2)), (sp.cos(theta), z/sp.sqrt(x**2 + y**2 + z**2)) ] # the cos(theta) dependence encoded by the associated Legendre poly expr = sp.assoc_legendre(l, m, sp.cos(theta)) # the exp(i*m*phi) dependence expr *= sp.expand_trig(sp.cos(m*phi)) + sp.I*sp.expand_trig(sp.sin(m*phi)) # simplifying optimizations expr = sp.together(expr.subs(defs)).subs(x**2 + y**2 + z**2, r**2) expr = expr.expand().subs([(x/r, xhat), (y/r, yhat), (z/r, zhat)]) expr = expr.factor().factor(extension=[sp.I]).subs(xhat+sp.I*yhat, xpyhat) expr = expr.subs(xhat**2 + yhat**2, 1-zhat**2).factor() # and finally add the normalization amp = sp.sqrt((2*l+1) / (4*numpy.pi) * sp.factorial(l-m) / sp.factorial(l+m)) expr *= amp return expr
def challenge16_9(): a, b, c = symbols('a b c') expr1 = (b * ((2 * a * cos(theta)) - b)) expr2 = ((a - c) * (c + a)) expr = (Eq(expr1, expr2)) print(solve(expr1)) print(expand_trig(expr1)) print(solve(expr2)) print(expand_trig(expr2)) print(solve(expr)) print(expand_trig(expr))
def form_to_fform(form, M=16): """Convert instance of `FormContainer` to instance of `fFormContainer` Parameters ---------- form : FormContainer Instance of :class:`~shgpy.core.data_handler.FormContainer` M : int, optional Number of Fourier frequencies, defaults to `16`. Returns ------- fform : fFormContainer Instance of :class:`~shgpy.core.data_handler.fFormContainer` Notes ----- This function operates by taking an instance of the `FormContainer` class and performing a Fourier transform. """ iterable = {} for k,v in form.get_items(): iterable[k] = np.zeros((2*M+1,), dtype=object) _logger.info(f'Currently computing {k}.') for m in np.arange(-M, M+1): _logger.debug(f'Currently computing m={m}.') expr = sp.expand_trig(v*(sp.cos(-m*S.phi)+1j*sp.sin(-m*S.phi))).expand() expr_re = _no_I_component(expr) expr_im = _I_component(expr) iterable[k][n2i(m, M)] = 1/2/sp.pi*sp.integrate(expr_re, (S.phi, 0, 2*sp.pi)) + 1/2/sp.pi*sp.I*sp.integrate(expr_im, (S.phi, 0, 2*sp.pi)) return fFormContainer(iterable, M=M)
def dddd(self, mu: int, nu: int, rho: int, sigma: int): """ Calculates the component of the Riemann tensor R_mu,nu,rho,sigma. Parameters ---------- mu : int The first lower index nu : int The second lower index rho : int The third lower index sigma : int The fourth lower index Returns ------- sympy expression the expression representing the specified component of the Riemann tensor """ if self.dddd_evaluated[mu, nu, rho, sigma]: return self.dddd_values[mu, nu, rho, sigma] R = 0 for lam in range(self.g.dim()): R += self.g.dd(mu, lam) * self.uddd(lam, nu, rho, sigma) self.dddd_values[mu, nu, rho, sigma] = sym.simplify(sym.expand_trig(R.simplify())) self.dddd_evaluated[mu, nu, rho, sigma] = True return self.dddd_values[mu, nu, rho, sigma]
def test_csch(): x, y = symbols('x,y') k = Symbol('k', integer=True) n = Symbol('n', positive=True) assert csch(nan) is nan assert csch(zoo) is nan assert csch(oo) == 0 assert csch(-oo) == 0 assert csch(0) is zoo assert csch(-1) == -csch(1) assert csch(-x) == -csch(x) assert csch(-pi) == -csch(pi) assert csch(-2**1024 * E) == -csch(2**1024 * E) assert csch(pi * I) is zoo assert csch(-pi * I) is zoo assert csch(2 * pi * I) is zoo assert csch(-2 * pi * I) is zoo assert csch(-3 * 10**73 * pi * I) is zoo assert csch(7 * 10**103 * pi * I) is zoo assert csch(pi * I / 2) == -I assert csch(-pi * I / 2) == I assert csch(pi * I * Rational(5, 2)) == -I assert csch(pi * I * Rational(7, 2)) == I assert csch(pi * I / 3) == -2 / sqrt(3) * I assert csch(pi * I * Rational(-2, 3)) == 2 / sqrt(3) * I assert csch(pi * I / 4) == -sqrt(2) * I assert csch(-pi * I / 4) == sqrt(2) * I assert csch(pi * I * Rational(7, 4)) == sqrt(2) * I assert csch(pi * I * Rational(-3, 4)) == sqrt(2) * I assert csch(pi * I / 6) == -2 * I assert csch(-pi * I / 6) == 2 * I assert csch(pi * I * Rational(7, 6)) == 2 * I assert csch(pi * I * Rational(-7, 6)) == -2 * I assert csch(pi * I * Rational(-5, 6)) == 2 * I assert csch(pi * I / 105) == -1 / sin(pi / 105) * I assert csch(-pi * I / 105) == 1 / sin(pi / 105) * I assert csch(x * I) == -1 / sin(x) * I assert csch(k * pi * I) is zoo assert csch(17 * k * pi * I) is zoo assert csch(k * pi * I / 2) == -1 / sin(k * pi / 2) * I assert csch(n).is_real is True assert expand_trig(csch(x + y)) == 1 / (sinh(x) * cosh(y) + cosh(x) * sinh(y))
def is_equal(self, eq1, eq2): """Compare answers""" #answer=eq1, solution=eq2 equation_types = [ Equality, Unequality, StrictLessThan, LessThan, StrictGreaterThan, GreaterThan ] #Symbolic equality/Perfect match if self._comparison_type == "perfect_match": return eq1 == eq2 eq1 = factor( simplify(eq1) ) #simplify is mandatory to counter expand_trig and expand_log weaknesses eq2 = factor(simplify(eq2)) #Trigonometric simplifications if self._use_trigo: eq1 = expand_trig(eq1) eq2 = expand_trig(eq2) #Logarithmic simplifications if self._use_log: if self._use_complex: eq1 = expand_log(eq1) eq2 = expand_log(eq2) else: eq1 = expand_log(eq1, force=True) eq2 = expand_log(eq2, force=True) if self._tolerance: eq1 = eq1.subs([(E, math.e), (pi, math.pi)]) eq2 = eq2.subs([(E, math.e), (pi, math.pi)]) #Numbers if (isinstance(eq1, Number) and isinstance(eq2, Number)) or self._tolerance: return round(float(abs(N(eq1 - eq2))), 10) <= round( float(self._tolerance), 10) if self._tolerance else abs( N(eq1 - eq2)) == 0 #Numerical Evaluation if not type(eq1) == type(eq2): return N(eq1) == N(eq2) #Equality and inequalities if type(eq1) in equation_types: return eq1 == eq2 or simplify(eq1) == simplify(eq2) #Direct match if eq1 == eq2 or simplify(eq1) == simplify(eq2): return True #Uncaught return abs(N(eq1 - eq2)) == 0
def expands_trig(expression): ''' Expand a trig function Syntax: sympy.expand_trig(expression) ''' return expand_trig(expression)
def sin(x): if isinstance(x, sp.core.basic.Basic): s = sp.sin(x) s = sp.expand_trig(s) s = sp.simplify(s) s = sp.trigsimp(s) return s else: return np.sin(x)
def cos(x): if isinstance(x, sp.core.basic.Basic): c = sp.cos(x) c = sp.expand_trig(c) c = sp.simplify(c) c = sp.trigsimp(c) return c else: return np.cos(x)
def test_sech(): x, y = symbols('x, y') k = Symbol('k', integer=True) n = Symbol('n', positive=True) assert sech(nan) is nan assert sech(zoo) is nan assert sech(oo) == 0 assert sech(-oo) == 0 assert sech(0) == 1 assert sech(-1) == sech(1) assert sech(-x) == sech(x) assert sech(pi * I) == sec(pi) assert sech(-pi * I) == sec(pi) assert sech(-2**1024 * E) == sech(2**1024 * E) assert sech(pi * I / 2) is zoo assert sech(-pi * I / 2) is zoo assert sech((-3 * 10**73 + 1) * pi * I / 2) is zoo assert sech((7 * 10**103 + 1) * pi * I / 2) is zoo assert sech(pi * I) == -1 assert sech(-pi * I) == -1 assert sech(5 * pi * I) == -1 assert sech(8 * pi * I) == 1 assert sech(pi * I / 3) == 2 assert sech(pi * I * Rational(-2, 3)) == -2 assert sech(pi * I / 4) == sqrt(2) assert sech(-pi * I / 4) == sqrt(2) assert sech(pi * I * Rational(5, 4)) == -sqrt(2) assert sech(pi * I * Rational(-5, 4)) == -sqrt(2) assert sech(pi * I / 6) == 2 / sqrt(3) assert sech(-pi * I / 6) == 2 / sqrt(3) assert sech(pi * I * Rational(7, 6)) == -2 / sqrt(3) assert sech(pi * I * Rational(-5, 6)) == -2 / sqrt(3) assert sech(pi * I / 105) == 1 / cos(pi / 105) assert sech(-pi * I / 105) == 1 / cos(pi / 105) assert sech(x * I) == 1 / cos(x) assert sech(k * pi * I) == 1 / cos(k * pi) assert sech(17 * k * pi * I) == 1 / cos(17 * k * pi) assert sech(n).is_real is True assert expand_trig(sech(x + y)) == 1 / (cosh(x) * cosh(y) + sinh(x) * sinh(y))
def __init__(self, shape, wcs, theory=None, theory_norm=None, lensed_cls=None): ModeCoupling.__init__(self, shape, wcs) self.Lx, self.Ly, self.L = get_Ls() self.Ldl1 = (self.Lx * self.l1x + self.Ly * self.l1y) self.Ldl2 = (self.Lx * self.l2x + self.Ly * self.l2y) self.l1dl2 = (self.l1x * self.l2x + self.l2x * self.l2y) phi1 = Symbol('phi1') phi2 = Symbol('phi2') cos2t12 = sympy.cos(2 * (phi1 - phi2)) sin2t12 = sympy.sin(2 * (phi1 - phi2)) simpcos = sympy.expand_trig(cos2t12) simpsin = sympy.expand_trig(sin2t12) self.cos2t12 = sympy.expand( sympy.simplify( simpcos.subs([(sympy.cos(phi1), self.l1x / self.l1), (sympy.cos(phi2), self.l2x / self.l2), (sympy.sin(phi1), self.l1y / self.l1), (sympy.sin(phi2), self.l2y / self.l2)]))) self.sin2t12 = sympy.expand( sympy.simplify( simpsin.subs([(sympy.cos(phi1), self.l1x / self.l1), (sympy.cos(phi2), self.l2x / self.l2), (sympy.sin(phi1), self.l1y / self.l1), (sympy.sin(phi2), self.l2y / self.l2)]))) self.theory2d = None if theory is not None: self.theory2d = self._load_theory(theory, lensed_cls=lensed_cls) if theory_norm is None: self.theory2d_norm = self.theory2d else: self.theory2d_norm = self._load_theory(theory_norm, lensed_cls=lensed_cls) self.Als = {}
def secular_DF(e, e1, w, w1, order): """ Return the secular component of the disturbing function for coplanet planets up to the specified order in the planets' eccentricities for an inner plaent with eccentricity and longitude of periapse (e,w) and outer planet eccentricity/longitude of periape (e1,w1) """ s = 0 dw = w1 - w # Introduce `eps' as order parameter multiplying eccentricities. # 'eps' is set to 1 at teh end of calculation. eps = S('epsilon') maxM = int(np.floor(order / 2.)) for i in range(maxM + 1): term = secular_DF_harmonic_term(eps * e, eps * e1, dw, i, order) term = term.series(eps, 0, order + 1).removeO() s = s + expand_trig(term) return s.subs(eps, 1)
def fromTransformation(symbols, to_base_point): """ Creates a new metric from the given to_base_point transformation. Parameters ---------- symbols : numpy array or array_like of sympy.core.symbol.Symbol The symbols representing the different dimensions, e.g. `sympy.symbols('r theta z', real=True)` to_base_point : numpy array or array_like The transformation equation to get from the current coordinate system into the base coordinate system. Should be expressed using the `symbols` and sympy functions for, e.g., the cosine. Returns ------- Metric the (analytical) metric as derived from the transformation for a point into the base coordinate system """ if to_base_point is None: raise Exception( "You need to specify the point-to-base-transformation!") print("Reconstructing metric from point-to-base-transformation...") dim = len(to_base_point) partial_derivatives = [[0 for i in range(dim)] for i in range(dim)] for i in range(dim): for j in range(dim): partial_derivatives[i][j] = sym.diff(to_base_point[j], symbols[i]) g = [[0 for i in range(dim)] for i in range(dim)] for i in range(dim): for j in range(dim): for k in range(dim): g[i][j] += partial_derivatives[i][k] * partial_derivatives[ j][k] g[j][i] = g[i][j] = sym.simplify( sym.expand_trig(g[i][j].simplify())) # catch some zeros print("Metric successfully reconstructed!") return Metric(symbols, sym.Matrix(g), to_base_point)
def quantization_form(expr, initial_expand=True): """Brings a sympy expression on a form that the quantizers can understand. Parameters ---------- expr : sympy expression The expression. Typically a symbolic potential or kinetic term Returns ------- sympy expr The rewritten expression. """ if initial_expand: expr = sp.expand(expr) if expr.func == sp.Add: expr = sp.Add(*[ quantization_form(term, initial_expand=False) for term in expr.args ]) if expr.func == sp.Mul: expr = sp.Mul(*[ quantization_form(factor, initial_expand=False) for factor in expr.args ]) if (expr.func == sp.cos) or (expr.func == sp.sin): if expr.args[0].func == sp.Add: arg_terms = expr.args[0].args arg_terms_dummy = sp.symbols('arg_dummy0:' + str(len(arg_terms))) # The reason for these subs shenanigans are to ensure that we don't mess with the coefficients of the arguments, so cos(2x)->cos(2x) and not cos(2x)->2*cos(x)**2-1 expr = expr.subs([ (arg, arg_dummy) for arg, arg_dummy in zip(arg_terms, arg_terms_dummy) ]) expr = sp.expand_trig(expr) expr = expr.subs([ (arg_dummy, arg) for arg_dummy, arg in zip(arg_terms_dummy, arg_terms) ]) if initial_expand: # Used to cancel out terms expr = sp.expand(expr) return expr
def function_from_partials(df_dq, q, zero_constants=False): """Returns a function given a list of partial derivatives of the function and a list of variables of which the partial derivative is given. For a function f(q1, ..., qn): 'df_dq' is the list [∂ℱ/∂q1, ..., ∂ℱ/∂qn] 'q' is the list [q1, ..., qn] 'zero_constants' is True if zero should be used for integration constants. Symbols C, α1, ..., αn are used for integration constants. """ alpha = symbols('α1:{0}'.format(len(q) + 1)) f, zeta = symbols('C ζ') q_alpha = zip(q, alpha) for i, df_dqr in enumerate(df_dq): if hasattr(df_dqr, 'subs'): integrand = df_dqr.subs(dict(q_alpha[i + 1:])).subs(q[i], zeta) else: integrand = df_dqr f += integrate(expand_trig(integrand), (zeta, alpha[i], q[i])) if zero_constants: f = f.subs(dict(zip([symbols('C')] + list(alpha), [0] * (len(q) + 1)))) return f
def angles_to_complex(equations, angles, control_angles): x = {theta: sp.symbols(f'z_{i}') for i, theta in enumerate(angles)} u = {theta: sp.symbols(f'w_{i}') for i, theta in enumerate(control_angles)} substitutions = [] X = list(x.values()) + list(u.values()) for i, x_i in enumerate(x): z = x[x_i] substitutions += [(sp.sin(x_i), (z - 1 / z) / 2j), (sp.cos(x_i), (z + 1 / z) / 2)] for i, u_i in enumerate(u): z = u[u_i] substitutions += [(sp.sin(u_i), (z - 1 / z) / 2j), (sp.cos(u_i), (z + 1 / z) / 2)] out_equations = [ sp.expand_trig(equation).subs(substitutions) for equation in equations ] return X, out_equations, substitutions, (x, u)
v = p.vel(N).express(N).subs(kde_map).subs(eq_gen_speed_map) partials[p] = dict(zip(u, map(lambda x: v.diff(x, N), u))) u1d, u2d, u3d = ud = [x.diff(t) for x in u] for k, v in vc_map.items(): vc_map[k.diff(t)] = v.diff(t).subs(kde_map).subs(vc_map) # generalized active/inertia forces Fr, _ = generalized_active_forces(partials, forces + torques) Fr_star, _ = generalized_inertia_forces(partials, bodies, kde_map) print('Fr') for i, fr in enumerate(Fr, 1): print('{0}: {1}'.format(i, msprint(fr))) print('Fr_star') for i, fr in enumerate(Fr_star, 1): fr = trigsimp(expand(expand_trig(fr)), deep=True, recursive=True) print('{0}: {1}'.format(i, msprint(fr))) # The dynamical equations would be of the form Fr = Fr* (r = 1, 2, 3). Fr_expected = [ alpha2 + a * (R1 * cos(q1) - R3 * sin(q1)), b * (R1 * cos(q2) + R3 * sin(q2)), Q3 - R3 ] Fr_star_expected = [ -mA * (a_star**2 + kA**2) * u1d, -mB * ((b_star**2 + kB**2) * u2d - b_star * sin(q2) * u3d), -1 * ((mB + mC) * u3d - mB * b_star * sin(q2) * u2d + mB * b_star * cos(q2) * u2**2) ] for x, y in zip(Fr, Fr_expected): assert expand(x - y) == 0
def get_real_Ylm(l, m): """ Return a function that computes the real spherical harmonic of order (l,m) Parameters ---------- l : int the degree of the harmonic m : int the order of the harmonic; abs(m) <= l Returns ------- Ylm : callable a function that takes 4 arguments: (xhat, yhat, zhat) unit-normalized Cartesian coordinates and returns the specified Ylm References ---------- https://en.wikipedia.org/wiki/Spherical_harmonics#Real_form """ import sympy as sp # make sure l,m are integers l = int(l) m = int(m) # the relevant cartesian and spherical symbols x, y, z, r = sp.symbols('x y z r', real=True, positive=True) xhat, yhat, zhat = sp.symbols('xhat yhat zhat', real=True, positive=True) phi, theta = sp.symbols('phi theta') defs = [(sp.sin(phi), y / sp.sqrt(x**2 + y**2)), (sp.cos(phi), x / sp.sqrt(x**2 + y**2)), (sp.cos(theta), z / sp.sqrt(x**2 + y**2 + z**2))] # the normalization factors if m == 0: amp = sp.sqrt((2 * l + 1) / (4 * numpy.pi)) else: amp = sp.sqrt(2 * (2 * l + 1) / (4 * numpy.pi) * sp.factorial(l - abs(m)) / sp.factorial(l + abs(m))) # the cos(theta) dependence encoded by the associated Legendre poly expr = (-1)**m * sp.assoc_legendre(l, abs(m), sp.cos(theta)) # the phi dependence if m < 0: expr *= sp.expand_trig(sp.sin(abs(m) * phi)) elif m > 0: expr *= sp.expand_trig(sp.cos(m * phi)) # simplify expr = sp.together(expr.subs(defs)).subs(x**2 + y**2 + z**2, r**2) expr = amp * expr.expand().subs([(x / r, xhat), (y / r, yhat), (z / r, zhat)]) Ylm = sp.lambdify((xhat, yhat, zhat), expr, 'numexpr') # attach some meta-data Ylm.expr = expr Ylm.l = l Ylm.m = m return Ylm
def simp(x): return simplify(expand_trig(expand_complex(expand(x)))) def sinc(x): return sin(pi*x)/(pi*x)
def prep_geodesic_eqns(self, parameters: Dict = None): r""" Define geodesic equations. Args: parameters: dictionary of model parameter values to be used for equation substitutions Attributes: gstar_ij_tanbeta_mat (`Matrix`_): :math:`\dots` g_ij_tanbeta_mat (`Matrix`_): :math:`\dots` tanbeta_poly_eqn (:class:`~sympy.core.relational.Equality`): :math:`\dots` where :math:`a := \tan\alpha` tanbeta_eqn (:class:`~sympy.core.relational.Equality`): :math:`\tan{\left(\beta \right)} = \dots` where :math:`a := \tan\alpha` gstar_ij_tanalpha_mat (`Matrix`_): a symmetric tensor with components (using shorthand :math:`a := \tan\alpha`) :math:`g^*[1,1] = \dots` :math:`g^*[1,2] = g^*[2,1] = \dots` :math:`g^*[2,2] = \dots` gstar_ij_mat (`Matrix`_): a symmetric tensor with components (using shorthand :math:`a := \tan\alpha`, and with a particular choice of model parameters) :math:`g^*[1,1] = \dots` :math:`g^*[1,2] = g^*[2,1] = \dots` :math:`g^*[2,2] = \dots` g_ij_tanalpha_mat (`Matrix`_): a symmetric tensor with components (using shorthand :math:`a := \tan\alpha`) :math:`g[1,1] = \dots` :math:`g[1,2] = g[2,1] = \dots` :math:`g[2,2] = \dots` g_ij_mat (`Matrix`_): a symmetric tensor with components (using shorthand :math:`a := \tan\alpha`, and with a particular choice of model parameters) :math:`g[1,1] =\dots` :math:`g[1,2] = g[2,1] = \dots` :math:`g[2,2] = \dots` g_ij_mat_lambdified (function) : lambdified version of `g_ij_mat` gstar_ij_mat_lambdified (function) : lambdified version of `gstar_ij_mat` """ logging.info("gme.core.geodesic.prep_geodesic_eqns") self.gstar_ij_tanbeta_mat = None self.g_ij_tanbeta_mat = None self.tanbeta_poly_eqn = None self.tanbeta_eqn = None self.gstar_ij_tanalpha_mat = None self.gstar_ij_mat = None self.g_ij_tanalpha_mat = None self.g_ij_mat = None self.g_ij_mat_lambdified = None self.gstar_ij_mat_lambdified = None mu_eta_sub = {mu: self.mu_, eta: self.eta_} # if parameters is None: return H_ = self.H_eqn.rhs.subs(mu_eta_sub) # Assume indexing here ranges in [1,2] def p_i_lambda(i): return [px, pz][i - 1] # r_i_lambda = lambda i: [rx, rz][i-1] # rdot_i_lambda = lambda i: [rdotx, rdotz][i-1] def gstar_ij_lambda(i, j): return simplify( Rational(2, 2) * diff(diff(H_, p_i_lambda(i)), p_i_lambda(j))) gstar_ij_mat = Matrix([ [gstar_ij_lambda(1, 1), gstar_ij_lambda(2, 1)], [gstar_ij_lambda(1, 2), gstar_ij_lambda(2, 2)], ]) gstar_ij_pxpz_mat = gstar_ij_mat.subs({varphi_r(rvec): varphi}) g_ij_pxpz_mat = gstar_ij_mat.inv().subs({varphi_r(rvec): varphi}) cosbeta_eqn = Eq(cos(beta), 1 / sqrt(1 + tan(beta)**2)) sinbeta_eqn = Eq(sin(beta), sqrt(1 - 1 / (1 + tan(beta)**2))) sintwobeta_eqn = Eq(sin(2 * beta), cos(beta)**2 - sin(beta)**2) self.gstar_ij_tanbeta_mat = expand_trig( simplify(gstar_ij_pxpz_mat.subs(e2d( self.px_pz_tanbeta_eqn)))).subs(e2d(cosbeta_eqn)) self.g_ij_tanbeta_mat = expand_trig( simplify(g_ij_pxpz_mat.subs(e2d(self.px_pz_tanbeta_eqn)))).subs( e2d(cosbeta_eqn)) tanalpha_beta_eqn = self.tanalpha_beta_eqn.subs(mu_eta_sub) tanbeta_poly_eqn = Eq( numer(tanalpha_beta_eqn.rhs) - tanalpha_beta_eqn.lhs * denom(tanalpha_beta_eqn.rhs), 0, ).subs({tan(alpha): ta}) tanbeta_eqn = Eq(tan(beta), solve(tanbeta_poly_eqn, tan(beta))[0]) self.tanbeta_poly_eqn = tanbeta_poly_eqn self.tanbeta_eqn = tanbeta_eqn # Replace all refs to beta with refs to alpha self.gstar_ij_tanalpha_mat = (self.gstar_ij_tanbeta_mat.subs( e2d(sintwobeta_eqn)).subs(e2d(sinbeta_eqn)).subs( e2d(cosbeta_eqn)).subs(e2d(tanbeta_eqn))).subs(mu_eta_sub) self.gstar_ij_mat = (self.gstar_ij_tanalpha_mat.subs({ ta: tan(alpha) }).subs(e2d(self.tanalpha_rdot_eqn)).subs( e2d(self.varphi_rx_eqn.subs( {varphi_r(rvec): varphi}))).subs(parameters)).subs(mu_eta_sub) self.g_ij_tanalpha_mat = (expand_trig(self.g_ij_tanbeta_mat).subs( e2d(sintwobeta_eqn)).subs(e2d(sinbeta_eqn)).subs( e2d(cosbeta_eqn)).subs(e2d(tanbeta_eqn))).subs(mu_eta_sub) self.g_ij_mat = (self.g_ij_tanalpha_mat.subs({ ta: rdotz / rdotx }).subs(e2d(self.varphi_rx_eqn.subs( {varphi_r(rvec): varphi}))).subs(parameters)).subs(mu_eta_sub) self.g_ij_mat_lambdified = lambdify((rx, rdotx, rdotz, varepsilon), self.g_ij_mat, "numpy") self.gstar_ij_mat_lambdified = lambdify((rx, rdotx, rdotz, varepsilon), self.gstar_ij_mat, "numpy")
# Space variable x = sympy.Symbol('x') u = 0 exp = [] eig = [] for i in range(ns + nf): exp.append(expa(i)) eig.append(eigenfunctions(i)) u += coefficients[i] * exp[i] # Calculation of the nonlinearity nonlinear_term = sympy.collect( sympy.expand(sympy.expand_trig(nonlinearity(u))), [sympy.sin(x), sympy.cos(x)]) print("Nonlinearity:") print(nonlinear_term) # Projection of the nonlinearity # TODO: justify division by sqrt(pi) projections = [] for i in range(ns + nf): product = sympy.expand(nonlinear_term * sympy.expand_trig(eig[i])) result_integration = sympy.integrate(product, (x, L, R)) / sympy.sqrt(sympy.pi) projections.append(sympy.simplify(result_integration)) print(projections[i])
# 合并同类项 collect expr = x**2 + 2 * x + x + 1 print(sympy.collect(expr, x)) # 分式化简 cancel expr = (x**2 + 2 * x + 1) / (x**2 + x) print(sympy.cancel(expr)) # 分式裂项 apart expr = (4 * x**3 + 21 * x**2 + 10 * x + 12) / (x**4 + 5 * x**3 + 5 * x**2 + 4 * x) print(sympy.apart(expr)) # 三角化简 trigsimp expr = sympy.sin(x) / sympy.cos(x) print(sympy.trigsimp(expr)) # 三角展开 expand_trig expr = sympy.sin(x + y) print(sympy.expand_trig(expr)) # 指数化简 powsimp / 指数展开 expand_power_exp a, b = sympy.symbols('a b') expr = x**a * x**b print(sympy.powsimp(expr)) # 化简指数的指数 powdenest # 必须满足条件 底数 positive=True x = sympy.symbols('x', positive=True) expr = (x**a)**b print(sympy.powdenest(expr)) # 对数展开 expand_log / 对数合并 logcombine # 需要指出 log ln 在 sympy 中都是自然对数 # symbol 也需要满足条件 x, y = sympy.symbols('x y', positive=True) n = sympy.symbols('n', real=True) print(sympy.expand_log(sympy.log(x**n)))
from sympy.physics.mechanics import dot, dynamicsymbols, inertia, msprint m, B11, B22, B33, B12, B23, B31 = symbols('m B11 B22 B33 B12 B23 B31') q1, q2, q3, q4, q5, q6 = dynamicsymbols('q1:7') # reference frames A = ReferenceFrame('A') B = A.orientnew('B', 'body', [q4, q5, q6], 'xyz') omega = B.ang_vel_in(A) # points B*, O pB_star = Point('B*') pO = pB_star.locatenew('O', q1*B.x + q2*B.y + q3*B.z) pO.set_vel(A, 0) pO.set_vel(B, 0) pB_star.v2pt_theory(pO, A, B) # rigidbody B I_B_O = inertia(B, B11, B22, B33, B12, B23, B31) rbB = RigidBody('rbB', pB_star, B, m, (I_B_O, pO)) # kinetic energy K = rbB.kinetic_energy(A) print('K = {0}'.format(msprint(trigsimp(K)))) K_expected = dot(dot(omega, I_B_O), omega)/2 print('K_expected = 1/2*omega*I*omega = {0}'.format( msprint(trigsimp(K_expected)))) assert expand(expand_trig(K - K_expected)) == 0
init_printing() from sympy import (symbols, sin, expand, expand_trig) #%% 1.- print('1.-') x, y = symbols('x y') # Consola: 'expr1' expr1 = (x**3 + 3 * y + 2)**2 sol1 = expr1.expand() # Consola: 'sol1' #%% 2.- print('2.-') expr2 = (3 * x**2 - 2 * x + 1) / (x - 1)**2 # Consola: 'expr2' sol2 = expr2.apart() # Consola: 'sol2' #%% 3.- print('3.-') expr3 = x**3 + 9 * x**2 + 27 * x + 27 # Consola: 'expr3' sol3 = expr3.factor() # Consola: 'sol3' #%% 4.- print('4.-') expr4 = sin(x + 2 * y) # Consola: 'expr4' expr4_exp = expand(expr4) expr4_exp2 = expand_trig(expr4) sol4 = expand(expr4, trig=True) # Consola: 'sol4'
for k, v in kde_map.items(): kde_map[k.diff(t)] = v.diff(t) # f1, f2 are forces the panes of glass exert on P1, P2 respectively R1 = f1*B.z + C*E.x - m1*g*B.y R2 = f2*B.z - C*E.x - m2*g*B.y forces = [(pP1, R1), (pP2, R2)] system = [Particle('P1', pP1, m1), Particle('P2', pP2, m2)] partials = partial_velocities([pP1, pP2], u, A, kde_map) Fr, _ = generalized_active_forces(partials, forces) Fr_star, _ = generalized_inertia_forces(partials, system, kde_map) # dynamical equations dyn_eq = [x + y for x, y in zip(Fr, Fr_star)] u1d, u2d, u3d = ud = [x.diff(t) for x in u] dyn_eq_map = solve(dyn_eq, ud) for x in ud: print('{0} = {1}'.format(msprint(x), msprint(cancel(trigsimp(dyn_eq_map[x]))))) u1d_expected = (-g*sin(q3) + omega**2*q1*cos(q3) + u2*u3 + (omega**2*cos(q3)**2 + u3**2)*L*m2/(m1 + m2)) u2d_expected = -g*cos(q3) - (omega**2*q1*sin(q3) + u3*u1) u3d_expected = -omega**2*sin(q3)*cos(q3) assert expand(cancel(expand_trig(dyn_eq_map[u1d] - u1d_expected))) == 0 assert expand(cancel(expand_trig(dyn_eq_map[u2d] - u2d_expected))) == 0 assert expand(expand_trig(dyn_eq_map[u3d] - u3d_expected)) == 0
def simp(x): return simplify(expand_trig(expand_complex(expand(x))))
def expand_trig(self): return SymbolicVector(expand_trig(self.x), expand_trig(self.y), expand_trig(self.z))
v = p.vel(N).express(N).subs(kde_map).subs(eq_gen_speed_map) partials[p] = dict(zip(u, map(lambda x: v.diff(x, N), u))) u1d, u2d, u3d = ud = [x.diff(t) for x in u] for k, v in vc_map.items(): vc_map[k.diff(t)] = v.diff(t).subs(kde_map).subs(vc_map) # generalized active/inertia forces Fr, _ = generalized_active_forces(partials, forces + torques) Fr_star, _ = generalized_inertia_forces(partials, bodies, kde_map) print('Fr') for i, fr in enumerate(Fr, 1): print('{0}: {1}'.format(i, msprint(fr))) print('Fr_star') for i, fr in enumerate(Fr_star, 1): fr = trigsimp(expand(expand_trig(fr)), deep=True, recursive=True) print('{0}: {1}'.format(i, msprint(fr))) # The dynamical equations would be of the form Fr = Fr* (r = 1, 2, 3). Fr_expected = [ alpha2 + a*(R1*cos(q1) - R3*sin(q1)), b*(R1*cos(q2) + R3*sin(q2)), Q3 - R3] Fr_star_expected = [ -mA*(a_star**2 + kA**2)*u1d, -mB*((b_star**2 + kB**2)*u2d - b_star*sin(q2)*u3d), -1*((mB + mC)*u3d - mB*b_star*sin(q2)*u2d + mB*b_star*cos(q2)*u2**2)] for x, y in zip(Fr, Fr_expected): assert expand(x - y) == 0 for x, y in zip(Fr_star, Fr_star_expected): assert trigsimp(expand(expand_trig((x - y).subs(vc_map)))) == 0
def _expand_trig(): # 展开三角函数 x = sympy.Symbol('x') y = sympy.Symbol('y') print(sympy.expand_trig(sympy.sin(x + y)))
pO = Point('O') pS_star = pO.locatenew('S*', b*A.y) pS_hat = pS_star.locatenew('S^', -r*B.y) # S^ touches the cone pS1 = pS_star.locatenew('S1', -r*A.z) # S1 touches horizontal wall of the race pS2 = pS_star.locatenew('S2', r*A.y) # S2 touches vertical wall of the race pO.set_vel(R, 0) pS_star.v2pt_theory(pO, R, A) pS1.v2pt_theory(pS_star, R, S) pS2.v2pt_theory(pS_star, R, S) # Since S is rolling against R, v_S1_R = 0, v_S2_R = 0. vc = [dot(p.vel(R), basis) for p in [pS1, pS2] for basis in R] pO.set_vel(C, 0) pS_star.v2pt_theory(pO, C, A) pS_hat.v2pt_theory(pS_star, C, S) # Since S is rolling against C, v_S^_C = 0. # Cone has only angular velocity in R.z direction. vc += [dot(pS_hat.vel(C), basis).subs(vc_map) for basis in A] vc += [dot(C.ang_vel_in(R), basis) for basis in [R.x, R.y]] vc_map = solve(vc, u) # Pure rolling between S and C, dot(ω_C_S, B.y) = 0. b_val = solve([dot(C.ang_vel_in(S), B.y).subs(vc_map).simplify()], b)[0][0] print('b = {0}'.format(msprint(collect(cancel(expand_trig(b_val)), r)))) b_expected = r*(1 + sin(theta))/(cos(theta) - sin(theta)) assert trigsimp(b_val - b_expected) == 0
def test_coth(): x, y = symbols('x,y') k = Symbol('k', integer=True) assert coth(nan) is nan assert coth(zoo) is nan assert coth(oo) == 1 assert coth(-oo) == -1 assert coth(0) is zoo assert unchanged(coth, 1) assert coth(-1) == -coth(1) assert unchanged(coth, x) assert coth(-x) == -coth(x) assert coth(pi * I) == -I * cot(pi) assert coth(-pi * I) == cot(pi) * I assert unchanged(coth, 2**1024 * E) assert coth(-2**1024 * E) == -coth(2**1024 * E) assert coth(pi * I) == -I * cot(pi) assert coth(-pi * I) == I * cot(pi) assert coth(2 * pi * I) == -I * cot(2 * pi) assert coth(-2 * pi * I) == I * cot(2 * pi) assert coth(-3 * 10**73 * pi * I) == I * cot(3 * 10**73 * pi) assert coth(7 * 10**103 * pi * I) == -I * cot(7 * 10**103 * pi) assert coth(pi * I / 2) == 0 assert coth(-pi * I / 2) == 0 assert coth(pi * I * Rational(5, 2)) == 0 assert coth(pi * I * Rational(7, 2)) == 0 assert coth(pi * I / 3) == -I / sqrt(3) assert coth(pi * I * Rational(-2, 3)) == -I / sqrt(3) assert coth(pi * I / 4) == -I assert coth(-pi * I / 4) == I assert coth(pi * I * Rational(17, 4)) == -I assert coth(pi * I * Rational(-3, 4)) == -I assert coth(pi * I / 6) == -sqrt(3) * I assert coth(-pi * I / 6) == sqrt(3) * I assert coth(pi * I * Rational(7, 6)) == -sqrt(3) * I assert coth(pi * I * Rational(-5, 6)) == -sqrt(3) * I assert coth(pi * I / 105) == -cot(pi / 105) * I assert coth(-pi * I / 105) == cot(pi / 105) * I assert unchanged(coth, 2 + 3 * I) assert coth(x * I) == -cot(x) * I assert coth(k * pi * I) == -cot(k * pi) * I assert coth(17 * k * pi * I) == -cot(17 * k * pi) * I assert coth(k * pi * I) == -cot(k * pi) * I assert coth(log(tan(2))) == coth(log(-tan(2))) assert coth(1 + I * pi / 2) == tanh(1) assert coth(x).as_real_imag( deep=False) == (sinh(re(x)) * cosh(re(x)) / (sin(im(x))**2 + sinh(re(x))**2), -sin(im(x)) * cos(im(x)) / (sin(im(x))**2 + sinh(re(x))**2)) x = Symbol('x', extended_real=True) assert coth(x).as_real_imag(deep=False) == (coth(x), 0) assert expand_trig(coth(2 * x)) == (coth(x)**2 + 1) / (2 * coth(x)) assert expand_trig(coth( 3 * x)) == (coth(x)**3 + 3 * coth(x)) / (1 + 3 * coth(x)**2) assert expand_trig( coth(x + y)) == (1 + coth(x) * coth(y)) / (coth(x) + coth(y))
# print(a) x = sym.symbols("x") y = sym.symbols("y") z = sym.symbols("z") # simplify function a = sym.simplify(sym.sin(x)**2 + sym.cos(x)**2) b = sym.simplify((x**3 + x**2 - x - 1) / (x**2 + 2 * x + 1)) print(f"simplification of sin(x)**2 + cos(x)**2= {a}") print(f"simplification of (x**3 + x**2 - x - 1)/(x**2 + 2*x + 1) = {b}") # expand function c = sym.expand((x + 1)**2) d = sym.expand((x + 2) * (x + 3)) e = sym.expand_trig(sym.sin(x + y)) print(f"Development of (x + 1)**2 = {c}") print(f"Development of (x+2)*(x+3) = {d}") print(f"Development of sin(x+y) = {e}") # factor function f = sym.factor(x**2 * z + 4 * x * y * z + a * y**2 * z) g = sym.factor(sym.cos(x)**2 + 2 * sym.cos(x) * sym.sin(x) + sym.sin(x)**2) print(f"Factor of x**2*z + 4*x*y*z + a*y**2*z = {f}") print(f"Factor of cos(x)**x + 2*cos(x)*sin(x) + sin(x)**2 = {g}") # derivative function h = sym.diff(sym.cos(x), x) i = sym.diff(x**4, x, 3) print(f"The derivative of cos(x) = {h}") print(f"The 3rd derivative of x**4 = {i}")