Coordinate Functions¶

In the context of a topological manifold $$M$$ over a topological field $$K$$, a coordinate function is a function from a chart codomain to $$K$$. In other words, a coordinate function is a $$K$$-valued function of the coordinates associated to some chart.

More precisely, let $$(U, \varphi)$$ be a chart on $$M$$, i.e. $$U$$ is an open subset of $$M$$ and $$\varphi: U \to V \subset K^n$$ is a homeomorphism from $$U$$ to an open subset $$V$$ of $$K^n$$. A coordinate function associated to the chart $$(U, \varphi)$$ is a function

$\begin{split}\begin{array}{cccc} f:& V\subset K^n & \longrightarrow & K \\ & (x^1, \ldots, x^n) & \longmapsto & f(x^1, \ldots, x^n) \end{array}\end{split}$

Coordinate functions are implemented by derived classes of the abstract base class CoordFunction.

The class MultiCoordFunction implements $$K^m$$-valued functions of the coordinates of a chart, with $$m$$ a positive integer.

AUTHORS:

• Eric Gourgoulhon, Michal Bejger (2013-2015) : initial version
• Travis Scrimshaw (2016) : make CoordFunction inheritate from AlgebraElement
class sage.manifolds.coord_func.CoordFunction(parent)

Abstract base class for coordinate functions.

If $$(U, \varphi)$$ is a chart on a topological manifold $$M$$ of dimension $$n$$ over a topological field $$K$$, a coordinate function associated to $$(U, \varphi)$$ is a map $$f: V \subset K^n \to K$$, where $$V$$ is the codomain of $$\varphi$$. In other words, $$f$$ is a $$K$$-valued function of the coordinates associated to the chart $$(U, \varphi)$$.

The class CoordFunction is an abstract one. Specific coordinate functions must be implemented by derived classes, like CoordFunctionSymb for symbolic coordinate functions.

INPUT:

• parent – the algebra of coordinate functions on a given chart
arccos()

Arc cosine of self.

OUTPUT:

• coordinate function $$\arccos(f)$$, where $$f$$ is the current coordinate function

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.arccos()
Traceback (most recent call last):
...
NotImplementedError: <abstract method arccos at 0x...>
arccosh()

Inverse hyperbolic cosine of self.

OUTPUT:

• coordinate function $$\mathrm{arcosh}(f)$$, where $$f$$ is the current coordinate function

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.arccosh()
Traceback (most recent call last):
...
NotImplementedError: <abstract method arccosh at 0x...>
arcsin()

Arc sine of self.

OUTPUT:

• coordinate function $$\arcsin(f)$$, where $$f$$ is the current coordinate function

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.arcsin()
Traceback (most recent call last):
...
NotImplementedError: <abstract method arcsin at 0x...>
arcsinh()

Inverse hyperbolic sine of self.

OUTPUT:

• coordinate function $$\mathrm{arsinh}(f)$$, where $$f$$ is the current coordinate function

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.arcsinh()
Traceback (most recent call last):
...
NotImplementedError: <abstract method arcsinh at 0x...>
arctan()

Arc tangent of self.

OUTPUT:

• coordinate function $$\arctan(f)$$, where $$f$$ is the current coordinate function

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.arctan()
Traceback (most recent call last):
...
NotImplementedError: <abstract method arctan at 0x...>
arctanh()

Inverse hyperbolic tangent of self.

OUTPUT:

• coordinate function $$\mathrm{artanh}(f)$$, where $$f$$ is the current coordinate function

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.arctanh()
Traceback (most recent call last):
...
NotImplementedError: <abstract method arctanh at 0x...>
chart()

Return the chart with respect to which self is defined.

OUTPUT:

EXAMPLE:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: f = X.function(1+x+y^2)
sage: f.chart()
Chart (M, (x, y))
sage: f.chart() is X
True
copy()

Return an exact copy of the object.

OUTPUT:

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.copy()
Traceback (most recent call last):
...
NotImplementedError: <abstract method copy at 0x...>
cos()

Cosine of self.

OUTPUT:

• coordinate function $$\cos(f)$$, where $$f$$ is the current coordinate function

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.cos()
Traceback (most recent call last):
...
NotImplementedError: <abstract method cos at 0x...>
cosh()

Hyperbolic cosine of self.

OUTPUT:

• coordinate function $$\cosh(f)$$, where $$f$$ is the current coordinate function

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.cosh()
Traceback (most recent call last):
...
NotImplementedError: <abstract method cosh at 0x...>
diff(coord)

Return the partial derivative of self with respect to a coordinate.

INPUT:

• coord – either the coordinate $$x^i$$ with respect to which the derivative of the coordinate function $$f$$ is to be taken, or the index $$i$$ labelling this coordinate (with the index convention defined on the chart domain via the parameter start_index)

OUTPUT:

• instance of CoordFunction representing the partial derivative $$\frac{\partial f}{\partial x^i}$$

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.diff(x)
Traceback (most recent call last):
...
NotImplementedError: <abstract method diff at 0x...>
disp()

Display the function in arrow notation.

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.display()
Traceback (most recent call last):
...
NotImplementedError: <abstract method display at 0x...>
display()

Display the function in arrow notation.

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.display()
Traceback (most recent call last):
...
NotImplementedError: <abstract method display at 0x...>
exp()

Exponential of self.

OUTPUT:

• coordinate function $$\exp(f)$$, where $$f$$ is the current coordinate function.

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.exp()
Traceback (most recent call last):
...
NotImplementedError: <abstract method exp at 0x...>
expr()

Return some data that, along with the chart, is sufficient to reconstruct the object.

For a symbolic coordinate function, this returns the symbol expression representing the function (see sage.manifolds.coord_func_symb.CoordFunctionSymb.expr())

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.expr()
Traceback (most recent call last):
...
NotImplementedError: <abstract method expr at 0x...>
is_zero()

Return True if the function is zero and False otherwise.

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.is_zero()
Traceback (most recent call last):
...
NotImplementedError: <abstract method is_zero at 0x...>
log(base=None)

Logarithm of self.

INPUT:

• base – (default: None) base of the logarithm; if None, the natural logarithm (i.e. logarithm to base e) is returned

OUTPUT:

• coordinate function $$\log_a(f)$$, where $$f$$ is the current coordinate function and $$a$$ is the base

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.log()
Traceback (most recent call last):
...
NotImplementedError: <abstract method log at 0x...>
scalar_field(name=None, latex_name=None)

Construct the scalar field that has self as coordinate expression.

The domain of the scalar field is the open subset covered by the chart on which self is defined.

INPUT:

• name – (default: None) name given to the scalar field
• latex_name – (default: None) LaTeX symbol to denote the scalar field; if None, the LaTeX symbol is set to name

OUTPUT:

EXAMPLES:

Construction of a scalar field on a 2-dimensional manifold:

sage: M = Manifold(2, 'M', structure='topological')
sage: c_xy.<x,y> = M.chart()
sage: fc = c_xy.function(x+2*y^3)
sage: f = fc.scalar_field() ; f
Scalar field on the 2-dimensional topological manifold M
sage: f.display()
M --> R
(x, y) |--> 2*y^3 + x
sage: f.coord_function(c_xy) is fc
True
sin()

Sine of self.

OUTPUT:

• coordinate function $$\sin(f)$$, where $$f$$ is the current coordinate function

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.sin()
Traceback (most recent call last):
...
NotImplementedError: <abstract method sin at 0x...>
sinh()

Hyperbolic sine of self.

OUTPUT:

• coordinate function $$\sinh(f)$$, where $$f$$ is the current coordinate function

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.sinh()
Traceback (most recent call last):
...
NotImplementedError: <abstract method sinh at 0x...>
sqrt()

Square root of self.

OUTPUT:

• coordinate function $$\sqrt{f}$$, where $$f$$ is the current coordinate function

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.sqrt()
Traceback (most recent call last):
...
NotImplementedError: <abstract method sqrt at 0x...>
tan()

Tangent of self.

OUTPUT:

• coordinate function $$\tan(f)$$, where $$f$$ is the current coordinate function

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.tan()
Traceback (most recent call last):
...
NotImplementedError: <abstract method tan at 0x...>
tanh()

Hyperbolic tangent of self.

OUTPUT:

• coordinate function $$\tanh(f)$$, where $$f$$ is the current coordinate function

TESTS:

This method must be implemented by derived classes; it is not implemented here:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: from sage.manifolds.coord_func import CoordFunction
sage: f = CoordFunction(X.function_ring())
sage: f.tanh()
Traceback (most recent call last):
...
NotImplementedError: <abstract method tanh at 0x...>
class sage.manifolds.coord_func.MultiCoordFunction(chart, expressions)

Coordinate function to some Cartesian power of the base field.

If $$n$$ and $$m$$ are two positive integers and $$(U, \varphi)$$ is a chart on a topological manifold $$M$$ of dimension $$n$$ over a topological field $$K$$, a multi-coordinate function associated to $$(U, \varphi)$$ is a map

$\begin{split}\begin{array}{llcl} f:& V \subset K^n & \longrightarrow & K^m \\ & (x^1, \ldots, x^n) & \longmapsto & (f_1(x^1, \ldots, x^n), \ldots, f_m(x^1, \ldots, x^n)), \end{array}\end{split}$

where $$V$$ is the codomain of $$\varphi$$. In other words, $$f$$ is a $$K^m$$-valued function of the coordinates associated to the chart $$(U, \varphi)$$. Each component $$f_i$$ ($$1 \leq i \leq m$$) is a coordinate function and is therefore stored as a CoordFunction.

INPUT:

• chart – the chart $$(U, \varphi)$$
• expressions – list (or tuple) of length $$m$$ of elements to construct the coordinate functions $$f_i$$ ($$1 \leq i \leq m$$); for symbolic coordinate functions, this must be symbolic expressions involving the chart coordinates, while for numerical coordinate functions, this must be data file names

EXAMPLES:

A function $$f: V \subset \RR^2 \longrightarrow \RR^3$$:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: f = X.multifunction(x-y, x*y, cos(x)*exp(y)); f
Coordinate functions (x - y, x*y, cos(x)*e^y) on the Chart (M, (x, y))
sage: type(f)
<class 'sage.manifolds.coord_func.MultiCoordFunction'>
sage: f(x,y)
(x - y, x*y, cos(x)*e^y)
sage: latex(f)
\left(x - y, x y, \cos\left(x\right) e^{y}\right)

Each real-valued function $$f_i$$ ($$1 \leq i \leq m$$) composing $$f$$ can be accessed via the square-bracket operator, by providing $$i-1$$ as an argument:

sage: f[0]
x - y
sage: f[1]
x*y
sage: f[2]
cos(x)*e^y

We can give a more verbose explanation of each function:

sage: f[0].display()
(x, y) |--> x - y

Each f[i-1] is an instance of CoordFunction:

sage: isinstance(f[0], sage.manifolds.coord_func.CoordFunction)
True

In the present case, f[i-1] is an instance of the subclass CoordFunctionSymb:

sage: type(f[0])
<class 'sage.manifolds.coord_func_symb.CoordFunctionSymbRing_with_category.element_class'>

A class MultiCoordFunction can represent a real-valued function (case $$m = 1$$), although one should rather employ the class CoordFunction for this purpose:

sage: g = X.multifunction(x*y^2)
sage: g(x,y)
(x*y^2,)

Evaluating the functions at specified coordinates:

sage: f(1,2)
(-1, 2, cos(1)*e^2)
sage: var('a b')
(a, b)
sage: f(a,b)
(a - b, a*b, cos(a)*e^b)
sage: g(1,2)
(4,)
chart()

Return the chart with respect to which self is defined.

OUTPUT:

EXAMPLES:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: f = X.multifunction(x-y, x*y, cos(x)*exp(y))
sage: f.chart()
Chart (M, (x, y))
sage: f.chart() is X
True
expr()

Return a tuple of data, the item no.i begin sufficient to reconstruct the coordinate function no. $$i$$.

In other words, if f is a multi-coordinate function, then f.chart().multifunction(*(f.expr())) results in a multi-coordinate function identical to f.

For a symbolic multi-coordinate function, expr() returns the tuple of the symbolic expressions of the coordinate functions composing the object.

EXAMPLES:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: f = X.multifunction(x-y, x*y, cos(x)*exp(y))
sage: f.expr()
(x - y, x*y, cos(x)*e^y)
sage: type(f.expr()[0])
<type 'sage.symbolic.expression.Expression'>

One shall always have:

sage: f.chart().multifunction(*(f.expr())) == f
True
jacobian()

Return the Jacobian matrix of the system of coordinate functions.

jacobian() is a 2-dimensional array of size $$m \times n$$, where $$m$$ is the number of functions and $$n$$ the number of coordinates, the generic element being $$J_{ij} = \frac{\partial f_i}{\partial x^j}$$ with $$1 \leq i \leq m$$ (row index) and $$1 \leq j \leq n$$ (column index).

OUTPUT:

• Jacobian matrix as a 2-dimensional array J of coordinate functions with J[i-1][j-1] being $$J_{ij} = \frac{\partial f_i}{\partial x^j}$$ for $$1 \leq i \leq m$$ and $$1 \leq j \leq n$$

EXAMPLES:

Jacobian of a set of 3 functions of 2 coordinates:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: f = X.multifunction(x-y, x*y, y^3*cos(x))
sage: f.jacobian()
[           1           -1]
[           y            x]
[ -y^3*sin(x) 3*y^2*cos(x)]

Each element of the result is a coordinate function:

sage: type(f.jacobian()[2,0])
<class 'sage.manifolds.coord_func_symb.CoordFunctionSymbRing_with_category.element_class'>
sage: f.jacobian()[2,0].display()
(x, y) |--> -y^3*sin(x)

Test of the computation:

sage: [[f.jacobian()[i,j] == f[i].diff(j) for j in range(2)] for i in range(3)]
[[True, True], [True, True], [True, True]]

Test with start_index = 1:

sage: M = Manifold(2, 'M', structure='topological', start_index=1)
sage: X.<x,y> = M.chart()
sage: f = X.multifunction(x-y, x*y, y^3*cos(x))
sage: f.jacobian()
[           1           -1]
[           y            x]
[ -y^3*sin(x) 3*y^2*cos(x)]
sage: [[f.jacobian()[i,j] == f[i].diff(j+1) for j in range(2)]  # note the j+1
....:                                         for i in range(3)]
[[True, True], [True, True], [True, True]]
jacobian_det()

Return the Jacobian determinant of the system of functions.

The number $$m$$ of coordinate functions must equal the number $$n$$ of coordinates.

OUTPUT:

EXAMPLES:

Jacobian determinant of a set of 2 functions of 2 coordinates:

sage: M = Manifold(2, 'M', structure='topological')
sage: X.<x,y> = M.chart()
sage: f = X.multifunction(x-y, x*y)
sage: f.jacobian_det()
x + y

The output of jacobian_det() is an instance of CoordFunction and can therefore be called on specific values of the coordinates, e.g. $$(x,y) = (1,2)$$:

sage: type(f.jacobian_det())
<class 'sage.manifolds.coord_func_symb.CoordFunctionSymbRing_with_category.element_class'>
sage: f.jacobian_det().display()
(x, y) |--> x + y
sage: f.jacobian_det()(1,2)
3

The result is cached:

sage: f.jacobian_det() is f.jacobian_det()
True

We verify the determinant of the Jacobian:

sage: f.jacobian_det() == det(matrix([[f[i].diff(j).expr() for j in range(2)]
....:                                 for i in range(2)]))
True

Jacobian determinant of a set of 3 functions of 3 coordinates:

sage: M = Manifold(3, 'M', structure='topological')
sage: X.<x,y,z> = M.chart()
sage: f = X.multifunction(x*y+z^2, z^2*x+y^2*z, (x*y*z)^3)
sage: f.jacobian_det().display()
(x, y, z) |--> 6*x^3*y^5*z^3 - 3*x^4*y^3*z^4 - 12*x^2*y^4*z^5 + 6*x^3*y^2*z^6

We verify the determinant of the Jacobian:

sage: f.jacobian_det() == det(matrix([[f[i].diff(j).expr() for j in range(3)]
....:                                 for i in range(3)]))
True