def solve_ODE_first_order(eq, f): """ solves many kinds of first order odes, different methods are used depending on the form of the given equation. Now the linear and Bernoulli cases are implemented. """ from sympy.integrals.integrals import integrate x = f.args[0] f = f.func #linear case: a(x)*f'(x)+b(x)*f(x)+c(x) = 0 a = Wild('a', exclude=[f(x)]) b = Wild('b', exclude=[f(x)]) c = Wild('c', exclude=[f(x)]) r = eq.match(a*diff(f(x),x) + b*f(x) + c) if r: t = C.exp(integrate(r[b]/r[a], x)) tt = integrate(t*(-r[c]/r[a]), x) return (tt + Symbol("C1"))/t #Bernoulli case: a(x)*f'(x)+b(x)*f(x)+c(x)*f(x)^n = 0 n = Wild('n', exclude=[f(x)]) r = eq.match(a*diff(f(x),x) + b*f(x) + c*f(x)**n) if r: t = C.exp((1-r[n])*integrate(r[b]/r[a],x)) tt = (r[n]-1)*integrate(t*r[c]/r[a],x) return ((tt + Symbol("C1"))/t)**(1/(1-r[n])) #other cases of first order odes will be implemented here raise NotImplementedError("solve_ODE_first_order: Cannot solve " + str(eq))
def solve_ODE_second_order(eq, f): """ solves many kinds of second order odes, different methods are used depending on the form of the given equation. Now the constanst coefficients case and a special case are implemented. """ x = f.args[0] f = f.func #constant coefficients case: af''(x)+bf'(x)+cf(x)=0 a = Wild('a', exclude=[x]) b = Wild('b', exclude=[x]) c = Wild('c', exclude=[x]) r = eq.match(a * f(x).diff(x, x) + c * f(x)) if r: return Symbol("C1") * C.sin(sqrt( r[c] / r[a]) * x) + Symbol("C2") * C.cos(sqrt(r[c] / r[a]) * x) r = eq.match(a * f(x).diff(x, x) + b * diff(f(x), x) + c * f(x)) if r: r1 = solve(r[a] * x**2 + r[b] * x + r[c], x) if r1[0].is_real: if len(r1) == 1: return (Symbol("C1") + Symbol("C2") * x) * exp(r1[0] * x) else: return Symbol("C1") * exp(r1[0] * x) + Symbol("C2") * exp( r1[1] * x) else: r2 = abs((r1[0] - r1[1]) / (2 * S.ImaginaryUnit)) return (Symbol("C2") * C.cos(r2 * x) + Symbol("C1") * C.sin(r2 * x)) * exp( (r1[0] + r1[1]) * x / 2) #other cases of the second order odes will be implemented here #special equations, that we know how to solve t = x * C.exp(f(x)) tt = a * t.diff(x, x) / t r = eq.match(tt.expand()) if r: return -solve_ODE_1(f(x), x) t = x * C.exp(-f(x)) tt = a * t.diff(x, x) / t r = eq.match(tt.expand()) if r: #check, that we've rewritten the equation correctly: #assert ( r[a]*t.diff(x,2)/t ) == eq.subs(f, t) return solve_ODE_1(f(x), x) neq = eq * C.exp(f(x)) / C.exp(-f(x)) r = neq.match(tt.expand()) if r: #check, that we've rewritten the equation correctly: #assert ( t.diff(x,2)*r[a]/t ).expand() == eq return solve_ODE_1(f(x), x) raise NotImplementedError("solve_ODE_second_order: cannot solve " + str(eq))
def solve_ODE_second_order(eq, f): """ solves many kinds of second order odes, different methods are used depending on the form of the given equation. So far the constants coefficients case and a special case are implemented. """ x = f.args[0] f = f.func #constant coefficients case: af''(x)+bf'(x)+cf(x)=0 a = Wild('a', exclude=[x]) b = Wild('b', exclude=[x]) c = Wild('c', exclude=[x]) r = eq.match(a*f(x).diff(x,x) + c*f(x)) if r: return Symbol("C1")*C.sin(sqrt(r[c]/r[a])*x)+Symbol("C2")*C.cos(sqrt(r[c]/r[a])*x) r = eq.match(a*f(x).diff(x,x) + b*diff(f(x),x) + c*f(x)) if r: r1 = solve(r[a]*x**2 + r[b]*x + r[c], x) if r1[0].is_real: if len(r1) == 1: return (Symbol("C1") + Symbol("C2")*x)*exp(r1[0]*x) else: return Symbol("C1")*exp(r1[0]*x) + Symbol("C2")*exp(r1[1]*x) else: r2 = abs((r1[0] - r1[1])/(2*S.ImaginaryUnit)) return (Symbol("C2")*C.cos(r2*x) + Symbol("C1")*C.sin(r2*x))*exp((r1[0] + r1[1])*x/2) #other cases of the second order odes will be implemented here #special equations, that we know how to solve a = Wild('a') t = x*C.exp(f(x)) tt = a*t.diff(x, x)/t r = eq.match(tt.expand()) if r: return -solve_ODE_1(f(x), x) t = x*C.exp(-f(x)) tt = a*t.diff(x, x)/t r = eq.match(tt.expand()) if r: #check, that we've rewritten the equation correctly: #assert ( r[a]*t.diff(x,2)/t ) == eq.subs(f, t) return solve_ODE_1(f(x), x) neq = eq*C.exp(f(x))/C.exp(-f(x)) r = neq.match(tt.expand()) if r: #check, that we've rewritten the equation correctly: #assert ( t.diff(x,2)*r[a]/t ).expand() == eq return solve_ODE_1(f(x), x) raise NotImplementedError("solve_ODE_second_order: cannot solve " + str(eq))
def eval(cls, n, m, theta, phi): n, m, theta, phi = [sympify(x) for x in (n, m, theta, phi)] # Handle negative index m and arguments theta, phi if m.could_extract_minus_sign(): m = -m return S.NegativeOne**m * C.exp(-2*I*m*phi) * Ynm(n, m, theta, phi) if theta.could_extract_minus_sign(): theta = -theta return Ynm(n, m, theta, phi) if phi.could_extract_minus_sign(): phi = -phi return C.exp(-2*I*m*phi) * Ynm(n, m, theta, phi)
def _eval_expand_func(self, **hints): n, m, theta, phi = self.args rv = (sqrt( (2 * n + 1) / (4 * pi) * C.factorial(n - m) / C.factorial(n + m)) * C.exp(I * m * phi) * assoc_legendre(n, m, C.cos(theta))) # We can do this because of the range of theta return rv.subs(sqrt(-cos(theta)**2 + 1), sin(theta))
def _eval_expand_func(self, **hints): n, m, theta, phi = self.args rv = ( sqrt((2 * n + 1) / (4 * pi) * C.factorial(n - m) / C.factorial(n + m)) * C.exp(I * m * phi) * assoc_legendre(n, m, C.cos(theta)) ) # We can do this because of the range of theta return rv.subs(sqrt(-cos(theta) ** 2 + 1), sin(theta))
def fdiff(self, argindex=4): if argindex == 1: # Diff wrt n raise ArgumentIndexError(self, argindex) elif argindex == 2: # Diff wrt m raise ArgumentIndexError(self, argindex) elif argindex == 3: # Diff wrt theta n, m, theta, phi = self.args return (m * C.cot(theta) * Ynm(n, m, theta, phi) + sqrt((n - m)*(n + m + 1)) * C.exp(-I*phi) * Ynm(n, m + 1, theta, phi)) elif argindex == 4: # Diff wrt phi n, m, theta, phi = self.args return I * m * Ynm(n, m, theta, phi) else: raise ArgumentIndexError(self, argindex)
def eval(cls, n, x): if not n.is_Number: # Symbolic result L_n(x) # L_{n}(-x) ---> exp(-x) * L_{-n-1}(x) # L_{-n}(x) ---> exp(x) * L_{n-1}(-x) if n.could_extract_minus_sign(): return C.exp(x) * laguerre(n-1, -x) # We can evaluate for some special values of x if x == S.Zero: return S.One elif x == S.NegativeInfinity: return S.Infinity elif x == S.Infinity: return S.NegativeOne**n * S.Infinity else: # n is a given fixed integer, evaluate into polynomial if n.is_negative: raise ValueError("The index n must be nonnegative integer (got %r)" % n) else: return laguerre_poly(n, x, 0)
def eval(cls, n, x): if not n.is_Number: # Symbolic result L_n(x) # L_{n}(-x) ---> exp(-x) * L_{-n-1}(x) # L_{-n}(x) ---> exp(x) * L_{n-1}(-x) if n.could_extract_minus_sign(): return C.exp(x) * laguerre(n - 1, -x) # We can evaluate for some special values of x if x == S.Zero: return S.One elif x == S.NegativeInfinity: return S.Infinity elif x == S.Infinity: return S.NegativeOne**n * S.Infinity else: # n is a given fixed integer, evaluate into polynomial if n.is_negative: raise ValueError( "The index n must be nonnegative integer (got %r)" % n) else: return laguerre_poly(n, x, 0)
def solve_ODE_first_order(eq, f): """ solves many kinds of first order odes, different methods are used depending on the form of the given equation. Now the linear case is implemented. """ from sympy.integrals.integrals import integrate x = f.args[0] f = f.func #linear case: a(x)*f'(x)+b(x)*f(x)+c(x) = 0 a = Wild('a', exclude=[f(x)]) b = Wild('b', exclude=[f(x)]) c = Wild('c', exclude=[f(x)]) r = eq.match(a * diff(f(x), x) + b * f(x) + c) if r: t = C.exp(integrate(r[b] / r[a], x)) tt = integrate(t * (-r[c] / r[a]), x) return (tt + Symbol("C1")) / t #other cases of first order odes will be implemented here raise NotImplementedError("solve_ODE_first_order: Cannot solve " + str(eq))
def fdiff(self, argindex=1): if argindex == 1: return 2*C.exp(-self.args[0]**2)/sqrt(S.Pi) else: raise ArgumentIndexError(self, argindex)
def _eval_rewrite_as_exp(self, arg): neg_exp, pos_exp = C.exp(-arg), C.exp(arg) return (pos_exp + neg_exp) / (pos_exp - neg_exp)
def _eval_rewrite_as_exp(self, arg): return (C.exp(arg) + C.exp(-arg)) / 2
def fdiff(self, argindex=1): if argindex == 1: return 2 * C.exp(-self.args[0]**2) / sqrt(S.Pi) else: raise ArgumentIndexError(self, argindex)
def _eval_rewrite_as_exp(self, arg): return (C.exp(arg) - C.exp(-arg)) / 2
def _eval_expand_func(self, **hints): n, m, theta, phi = self.args return (sqrt( (2 * n + 1) / (4 * pi) * C.factorial(n - m) / C.factorial(n + m)) * C.exp(I * m * phi) * assoc_legendre(n, m, C.cos(theta)))
def _eval_expand_func(self, **hints): n, m, theta, phi = self.args return (sqrt((2*n + 1)/(4*pi) * C.factorial(n - m)/C.factorial(n + m)) * C.exp(I*m*phi) * assoc_legendre(n, m, C.cos(theta)))