def symbol(a=None): """ Return a variable from the symbolic ring with the given name. If an expression is given, it is returned unchanged. """ if isinstance(a, Expression): return a return SR.symbol(a)
def _get_predefined_class(arg): r""" Return the signature of the predefined class given by the string ``arg``. The signature is given by a tuple following the syntax (base field, class type, name, LaTeX name, function). Modify this method to add new predefined characteristic classes. TESTS:: sage: from sage.manifolds.differentiable.characteristic_class import _get_predefined_class sage: _get_predefined_class('Chern') ('complex', 'multiplicative', 'c', 'c', x + 1) sage: _get_predefined_class('Pontryagin') ('real', 'multiplicative', 'p', 'p', x + 1) sage: _get_predefined_class('Euler') ('real', 'Pfaffian', 'e', 'e', x) """ if not isinstance(arg, str): raise TypeError("argument 'arg' must be string") # Define variable: x = SR.symbol('x') # Define dictionary. The syntax is as follows: # (field_type, class_type, name, latex_name, func) if arg == 'ChernChar': return ('complex', 'additive', 'ch', r'\mathrm{ch}', x.exp()) elif arg == 'Todd': return ('complex', 'additive', 'Td', r'\mathrm{Td}', x / (1 - (-x).exp())) elif arg == 'Chern': return ('complex', 'multiplicative', 'c', 'c', 1 + x) elif arg == 'Pontryagin': return ('real', 'multiplicative', 'p', 'p', 1 + x) elif arg == 'AHat': return ('real', 'multiplicative', 'A^', r'\hat{A}', x.sqrt() / (2 * (x.sqrt() / 2).sinh())) elif arg == 'Hirzebruch': return ('real', 'multiplicative', 'L', 'L', x.sqrt() / x.sqrt().tanh()) elif arg == 'Euler': return ('real', 'Pfaffian', 'e', 'e', x) else: raise ValueError("the characteristic class '{}' is ".format(arg) + "not predefined yet.")
def _get_coeff_list(self): r""" Return the list of coefficients of the Taylor expansion at zero of the function. TESTS:: sage: M = Manifold(2, 'M') sage: E = M.vector_bundle(1, 'E', field='complex') sage: c = E.characteristic_class(1+x) sage: c._get_coeff_list() [1, 1] """ pow_range = self._base_space._dim // 2 def_var = self._func.default_variable() # Use a complex variable without affecting the old one: new_var = SR.symbol('x_char_class_', domain='complex') if self._vbundle._field_type == 'real': if self._class_type == 'additive': func = self._func.subs({def_var: new_var ** 2}) / 2 elif self._class_type == 'multiplicative': # This could case problems in the real domain, where sqrt(x^2) # is simplified to |x|. However, the variable must be complex # anyway. func = self._func.subs({def_var : new_var**2}).sqrt() elif self._class_type == 'Pfaffian': # There are no canonical Pfaffian classes, however, consider the # projection onto the odd part of the function to keep the # matrices skew: func = (self._func.subs({def_var: new_var}) - self._func.subs({def_var: -new_var})) / 2 else: func = self._func.subs({def_var: new_var}) return func.taylor(new_var, 0, pow_range).coefficients(sparse=False)
def airy_bi(alpha, x=None, hold_derivative=True, **kwds): r""" The Airy Bi function The Airy Bi function `\operatorname{Bi}(x)` is (along with `\operatorname{Ai}(x)`) one of the two linearly independent standard solutions to the Airy differential equation `f''(x) - x f(x) = 0`. It is defined by the initial conditions: .. MATH:: \operatorname{Bi}(0)=\frac{1}{3^{1/6} \Gamma\left(\frac{2}{3}\right)}, \operatorname{Bi}'(0)=\frac{3^{1/6}}{ \Gamma\left(\frac{1}{3}\right)}. Another way to define the Airy Bi function is: .. MATH:: \operatorname{Bi}(x)=\frac{1}{\pi}\int_0^\infty \left[ \exp\left( xt -\frac{t^3}{3} \right) +\sin\left(xt + \frac{1}{3}t^3\right) \right ] dt. INPUT: - ``alpha`` -- Return the `\alpha`-th order fractional derivative with respect to `z`. For `\alpha = n = 1,2,3,\ldots` this gives the derivative `\operatorname{Bi}^{(n)}(z)`, and for `\alpha = -n = -1,-2,-3,\ldots` this gives the `n`-fold iterated integral. .. MATH:: f_0(z) = \operatorname{Bi}(z) f_n(z) = \int_0^z f_{n-1}(t) dt - ``x`` -- The argument of the function - ``hold_derivative`` -- Whether or not to stop from returning higher derivatives in terms of `\operatorname{Bi}(x)` and `\operatorname{Bi}'(x)` .. SEEALSO:: :func:`airy_ai` EXAMPLES:: sage: n, x = var('n x') sage: airy_bi(x) airy_bi(x) It can return derivatives or integrals:: sage: airy_bi(2, x) airy_bi(2, x) sage: airy_bi(1, x, hold_derivative=False) airy_bi_prime(x) sage: airy_bi(2, x, hold_derivative=False) x*airy_bi(x) sage: airy_bi(-2, x, hold_derivative=False) airy_bi(-2, x) sage: airy_bi(n, x) airy_bi(n, x) It can be evaluated symbolically or numerically for real or complex values:: sage: airy_bi(0) 1/3*3^(5/6)/gamma(2/3) sage: airy_bi(0.0) 0.614926627446001 sage: airy_bi(I) airy_bi(I) sage: airy_bi(1.0*I) 0.648858208330395 + 0.344958634768048*I The functions can be evaluated numerically using mpmath, which can compute the values to arbitrary precision, and scipy:: sage: airy_bi(2).n(prec=100) 3.2980949999782147102806044252 sage: airy_bi(2).n(algorithm='mpmath', prec=100) 3.2980949999782147102806044252 sage: airy_bi(2).n(algorithm='scipy') # rel tol 1e-10 3.2980949999782134 And the derivatives can be evaluated:: sage: airy_bi(1, 0) 3^(1/6)/gamma(1/3) sage: airy_bi(1, 0.0) 0.448288357353826 Plots:: sage: plot(airy_bi(x), (x, -10, 5)) + plot(airy_bi_prime(x), ....: (x, -10, 5), color='red') Graphics object consisting of 2 graphics primitives **References** - Abramowitz, Milton; Stegun, Irene A., eds. (1965), "Chapter 10" - :wikipedia:`Airy_function` """ # We catch the case with no alpha if x is None: x = alpha return airy_bi_simple(x, **kwds) # We take care of all other cases. if not alpha in ZZ and not isinstance(alpha, Expression): return airy_bi_general(alpha, x, **kwds) if hold_derivative: return airy_bi_general(alpha, x, **kwds) elif alpha == 0: return airy_bi_simple(x, **kwds) elif alpha == 1: return airy_bi_prime(x, **kwds) elif alpha > 1: # We use a different variable here because if x is a # particular value, we would be differentiating a constant # which would return 0. What we want is the value of # the derivative at the value and not the derivative of # a particular value of the function. v = SR.symbol() return derivative(airy_bi_simple(v, **kwds), v, alpha).subs({v: x}) else: return airy_bi_general(alpha, x, **kwds)
def airy_ai(alpha, x=None, hold_derivative=True, **kwds): r""" The Airy Ai function The Airy Ai function `\operatorname{Ai}(x)` is (along with `\operatorname{Bi}(x)`) one of the two linearly independent standard solutions to the Airy differential equation `f''(x) - x f(x) = 0`. It is defined by the initial conditions: .. MATH:: \operatorname{Ai}(0)=\frac{1}{2^{2/3} \Gamma\left(\frac{2}{3}\right)}, \operatorname{Ai}'(0)=-\frac{1}{2^{1/3}\Gamma\left(\frac{1}{3}\right)}. Another way to define the Airy Ai function is: .. MATH:: \operatorname{Ai}(x)=\frac{1}{\pi}\int_0^\infty \cos\left(\frac{1}{3}t^3+xt\right) dt. INPUT: - ``alpha`` -- Return the `\alpha`-th order fractional derivative with respect to `z`. For `\alpha = n = 1,2,3,\ldots` this gives the derivative `\operatorname{Ai}^{(n)}(z)`, and for `\alpha = -n = -1,-2,-3,\ldots` this gives the `n`-fold iterated integral. .. MATH:: f_0(z) = \operatorname{Ai}(z) f_n(z) = \int_0^z f_{n-1}(t) dt - ``x`` -- The argument of the function - ``hold_derivative`` -- Whether or not to stop from returning higher derivatives in terms of `\operatorname{Ai}(x)` and `\operatorname{Ai}'(x)` .. SEEALSO:: :func:`airy_bi` EXAMPLES:: sage: n, x = var('n x') sage: airy_ai(x) airy_ai(x) It can return derivatives or integrals:: sage: airy_ai(2, x) airy_ai(2, x) sage: airy_ai(1, x, hold_derivative=False) airy_ai_prime(x) sage: airy_ai(2, x, hold_derivative=False) x*airy_ai(x) sage: airy_ai(-2, x, hold_derivative=False) airy_ai(-2, x) sage: airy_ai(n, x) airy_ai(n, x) It can be evaluated symbolically or numerically for real or complex values:: sage: airy_ai(0) 1/3*3^(1/3)/gamma(2/3) sage: airy_ai(0.0) 0.355028053887817 sage: airy_ai(I) airy_ai(I) sage: airy_ai(1.0*I) 0.331493305432141 - 0.317449858968444*I The functions can be evaluated numerically either using mpmath. which can compute the values to arbitrary precision, and scipy:: sage: airy_ai(2).n(prec=100) 0.034924130423274379135322080792 sage: airy_ai(2).n(algorithm='mpmath', prec=100) 0.034924130423274379135322080792 sage: airy_ai(2).n(algorithm='scipy') # rel tol 1e-10 0.03492413042327323 And the derivatives can be evaluated:: sage: airy_ai(1, 0) -1/3*3^(2/3)/gamma(1/3) sage: airy_ai(1, 0.0) -0.258819403792807 Plots:: sage: plot(airy_ai(x), (x, -10, 5)) + plot(airy_ai_prime(x), ....: (x, -10, 5), color='red') Graphics object consisting of 2 graphics primitives REFERENCES: - Abramowitz, Milton; Stegun, Irene A., eds. (1965), "Chapter 10" - :wikipedia:`Airy_function` """ # We catch the case with no alpha if x is None: x = alpha return airy_ai_simple(x, **kwds) # We take care of all other cases. if alpha not in ZZ and not isinstance(alpha, Expression): return airy_ai_general(alpha, x, **kwds) if hold_derivative: return airy_ai_general(alpha, x, **kwds) elif alpha == 0: return airy_ai_simple(x, **kwds) elif alpha == 1: return airy_ai_prime(x, **kwds) elif alpha > 1: # We use a different variable here because if x is a # particular value, we would be differentiating a constant # which would return 0. What we want is the value of # the derivative at the value and not the derivative of # a particular value of the function. v = SR.symbol() return derivative(airy_ai_simple(v, **kwds), v, alpha).subs({v: x}) else: return airy_ai_general(alpha, x, **kwds)