Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" Differentiable Scalar Fields
Given a differentiable manifold `M` of class `C^k` over a topological field `K` (in most applications, `K = \RR` or `K = \CC`), a *differentiable scalar field* on `M` is a map
.. MATH::
f: M \longrightarrow K
of class `C^k`.
Differentiable scalar fields are implemented by the class :class:`DiffScalarField`.
AUTHORS:
- Eric Gourgoulhon, Michal Bejger (2013-2015): initial version - Eric Gourgoulhon (2018): operators gradient, Laplacian and d'Alembertian
REFERENCES:
- [KN1963]_ - [Lee2013]_ - [ONe1983]_
"""
#****************************************************************************** # Copyright (C) 2015, 2018 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr> # Copyright (C) 2015 Michal Bejger <bejger@camk.edu.pl> # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # http://www.gnu.org/licenses/ #******************************************************************************
r""" Differentiable scalar field on a differentiable manifold.
Given a differentiable manifold `M` of class `C^k` over a topological field `K` (in most applications, `K = \RR` or `K = \CC`), a *differentiable scalar field* defined on `M` is a map
.. MATH::
f: M \longrightarrow K
that is `k`-times continuously differentiable.
The class :class:`DiffScalarField` is a Sage *element* class, whose *parent* class is :class:`~sage.manifolds.differentiable.scalarfield_algebra.DiffScalarFieldAlgebra`. It inherits from the class :class:`~sage.manifolds.scalarfield.ScalarField` devoted to generic continuous scalar fields on topological manifolds.
INPUT:
- ``parent`` -- the algebra of scalar fields containing the scalar field (must be an instance of class :class:`~sage.manifolds.differentiable.scalarfield_algebra.DiffScalarFieldAlgebra`) - ``coord_expression`` -- (default: ``None``) coordinate expression(s) of the scalar field; this can be either
- a dictionary of coordinate expressions in various charts on the domain, with the charts as keys; - a single coordinate expression; if the argument ``chart`` is ``'all'``, this expression is set to all the charts defined on the open set; otherwise, the expression is set in the specific chart provided by the argument ``chart``
NB: If ``coord_expression`` is ``None`` or incomplete, coordinate expressions can be added after the creation of the object, by means of the methods :meth:`~sage.manifolds.scalarfield.ScalarField.add_expr`, :meth:`~sage.manifolds.scalarfield.ScalarField.add_expr_by_continuation` and :meth:`~sage.manifolds.scalarfield.ScalarField.set_expr` - ``chart`` -- (default: ``None``) chart defining the coordinates used in ``coord_expression`` when the latter is a single coordinate expression; if none is provided (default), the default chart of the open set is assumed. If ``chart=='all'``, ``coord_expression`` is assumed to be independent of the chart (constant scalar field). - ``name`` -- (default: ``None``) string; name (symbol) given to the scalar field - ``latex_name`` -- (default: ``None``) string; LaTeX symbol to denote the scalar field; if none is provided, the LaTeX symbol is set to ``name``
EXAMPLES:
A scalar field on the 2-sphere::
sage: M = Manifold(2, 'M') # the 2-dimensional sphere S^2 sage: U = M.open_subset('U') # complement of the North pole sage: c_xy.<x,y> = U.chart() # stereographic coordinates from the North pole sage: V = M.open_subset('V') # complement of the South pole sage: c_uv.<u,v> = V.chart() # stereographic coordinates from the South pole sage: M.declare_union(U,V) # S^2 is the union of U and V sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)), ....: intersection_name='W', ....: restrictions1= x^2+y^2!=0, ....: restrictions2= u^2+v^2!=0) sage: uv_to_xy = xy_to_uv.inverse() sage: f = M.scalar_field({c_xy: 1/(1+x^2+y^2), c_uv: (u^2+v^2)/(1+u^2+v^2)}, ....: name='f') ; f Scalar field f on the 2-dimensional differentiable manifold M sage: f.display() f: M --> R on U: (x, y) |--> 1/(x^2 + y^2 + 1) on V: (u, v) |--> (u^2 + v^2)/(u^2 + v^2 + 1)
For scalar fields defined by a single coordinate expression, the latter can be passed instead of the dictionary over the charts::
sage: g = U.scalar_field(x*y, chart=c_xy, name='g') ; g Scalar field g on the Open subset U of the 2-dimensional differentiable manifold M
The above is indeed equivalent to::
sage: g = U.scalar_field({c_xy: x*y}, name='g') ; g Scalar field g on the Open subset U of the 2-dimensional differentiable manifold M
Since ``c_xy`` is the default chart of ``U``, the argument ``chart`` can be skipped::
sage: g = U.scalar_field(x*y, name='g') ; g Scalar field g on the Open subset U of the 2-dimensional differentiable manifold M
The scalar field `g` is defined on `U` and has an expression in terms of the coordinates `(u,v)` on `W=U\cap V`::
sage: g.display() g: U --> R (x, y) |--> x*y on W: (u, v) |--> u*v/(u^4 + 2*u^2*v^2 + v^4)
Scalar fields on `M` can also be declared with a single chart::
sage: f = M.scalar_field(1/(1+x^2+y^2), chart=c_xy, name='f') ; f Scalar field f on the 2-dimensional differentiable manifold M
Their definition must then be completed by providing the expressions on other charts, via the method :meth:`~sage.manifolds.scalarfield.ScalarField.add_expr`, to get a global cover of the manifold::
sage: f.add_expr((u^2+v^2)/(1+u^2+v^2), chart=c_uv) sage: f.display() f: M --> R on U: (x, y) |--> 1/(x^2 + y^2 + 1) on V: (u, v) |--> (u^2 + v^2)/(u^2 + v^2 + 1)
We can even first declare the scalar field without any coordinate expression and provide them subsequently::
sage: f = M.scalar_field(name='f') sage: f.add_expr(1/(1+x^2+y^2), chart=c_xy) sage: f.add_expr((u^2+v^2)/(1+u^2+v^2), chart=c_uv) sage: f.display() f: M --> R on U: (x, y) |--> 1/(x^2 + y^2 + 1) on V: (u, v) |--> (u^2 + v^2)/(u^2 + v^2 + 1)
We may also use the method :meth:`~sage.manifolds.scalarfield.ScalarField.add_expr_by_continuation` to complete the coordinate definition using the analytic continuation from domains in which charts overlap::
sage: f = M.scalar_field(1/(1+x^2+y^2), chart=c_xy, name='f') ; f Scalar field f on the 2-dimensional differentiable manifold M sage: f.add_expr_by_continuation(c_uv, U.intersection(V)) sage: f.display() f: M --> R on U: (x, y) |--> 1/(x^2 + y^2 + 1) on V: (u, v) |--> (u^2 + v^2)/(u^2 + v^2 + 1)
A scalar field can also be defined by some unspecified function of the coordinates::
sage: h = U.scalar_field(function('H')(x, y), name='h') ; h Scalar field h on the Open subset U of the 2-dimensional differentiable manifold M sage: h.display() h: U --> R (x, y) |--> H(x, y) on W: (u, v) |--> H(u/(u^2 + v^2), v/(u^2 + v^2))
We may use the argument ``latex_name`` to specify the LaTeX symbol denoting the scalar field if the latter is different from ``name``::
sage: latex(f) f sage: f = M.scalar_field({c_xy: 1/(1+x^2+y^2), c_uv: (u^2+v^2)/(1+u^2+v^2)}, ....: name='f', latex_name=r'\mathcal{F}') sage: latex(f) \mathcal{F}
The coordinate expression in a given chart is obtained via the method :meth:`~sage.manifolds.scalarfield.ScalarField.expr`, which returns a symbolic expression::
sage: f.expr(c_uv) (u^2 + v^2)/(u^2 + v^2 + 1) sage: type(f.expr(c_uv)) <type 'sage.symbolic.expression.Expression'>
The method :meth:`~sage.manifolds.scalarfield.ScalarField.coord_function` returns instead a function of the chart coordinates, i.e. an instance of :class:`~sage.manifolds.chart_func.ChartFunction`::
sage: f.coord_function(c_uv) (u^2 + v^2)/(u^2 + v^2 + 1) sage: type(f.coord_function(c_uv)) <class 'sage.manifolds.chart_func.ChartFunctionRing_with_category.element_class'> sage: f.coord_function(c_uv).display() (u, v) |--> (u^2 + v^2)/(u^2 + v^2 + 1)
The value returned by the method :meth:`~sage.manifolds.scalarfield.ScalarField.expr` is actually the coordinate expression of the chart function::
sage: f.expr(c_uv) is f.coord_function(c_uv).expr() True
A constant scalar field is declared by setting the argument ``chart`` to ``'all'``::
sage: c = M.scalar_field(2, chart='all', name='c') ; c Scalar field c on the 2-dimensional differentiable manifold M sage: c.display() c: M --> R on U: (x, y) |--> 2 on V: (u, v) |--> 2
A shortcut is to use the method :meth:`~sage.manifolds.manifold.TopologicalManifold.constant_scalar_field`::
sage: c == M.constant_scalar_field(2) True
The constant value can be some unspecified parameter::
sage: var('a') a sage: c = M.constant_scalar_field(a, name='c') ; c Scalar field c on the 2-dimensional differentiable manifold M sage: c.display() c: M --> R on U: (x, y) |--> a on V: (u, v) |--> a
A special case of constant field is the zero scalar field::
sage: zer = M.constant_scalar_field(0) ; zer Scalar field zero on the 2-dimensional differentiable manifold M sage: zer.display() zero: M --> R on U: (x, y) |--> 0 on V: (u, v) |--> 0
It can be obtained directly by means of the function :meth:`~sage.manifolds.manifold.TopologicalManifold.zero_scalar_field`::
sage: zer is M.zero_scalar_field() True
A third way is to get it as the zero element of the algebra `C^k(M)` of scalar fields on `M` (see below)::
sage: zer is M.scalar_field_algebra().zero() True
By definition, a scalar field acts on the manifold's points, sending them to elements of the manifold's base field (real numbers in the present case)::
sage: N = M.point((0,0), chart=c_uv) # the North pole sage: S = M.point((0,0), chart=c_xy) # the South pole sage: E = M.point((1,0), chart=c_xy) # a point at the equator sage: f(N) 0 sage: f(S) 1 sage: f(E) 1/2 sage: h(E) H(1, 0) sage: c(E) a sage: zer(E) 0
A scalar field can be compared to another scalar field::
sage: f == g False
...to a symbolic expression::
sage: f == x*y False sage: g == x*y True sage: c == a True
...to a number::
sage: f == 2 False sage: zer == 0 True
...to anything else::
sage: f == M False
Standard mathematical functions are implemented::
sage: sqrt(f) Scalar field sqrt(f) on the 2-dimensional differentiable manifold M sage: sqrt(f).display() sqrt(f): M --> R on U: (x, y) |--> 1/sqrt(x^2 + y^2 + 1) on V: (u, v) |--> sqrt(u^2 + v^2)/sqrt(u^2 + v^2 + 1)
::
sage: tan(f) Scalar field tan(f) on the 2-dimensional differentiable manifold M sage: tan(f).display() tan(f): M --> R on U: (x, y) |--> sin(1/(x^2 + y^2 + 1))/cos(1/(x^2 + y^2 + 1)) on V: (u, v) |--> sin((u^2 + v^2)/(u^2 + v^2 + 1))/cos((u^2 + v^2)/(u^2 + v^2 + 1))
.. RUBRIC:: Arithmetics of scalar fields
Scalar fields on `M` (resp. `U`) belong to the algebra `C^k(M)` (resp. `C^k(U)`)::
sage: f.parent() Algebra of differentiable scalar fields on the 2-dimensional differentiable manifold M sage: f.parent() is M.scalar_field_algebra() True sage: g.parent() Algebra of differentiable scalar fields on the Open subset U of the 2-dimensional differentiable manifold M sage: g.parent() is U.scalar_field_algebra() True
Consequently, scalar fields can be added::
sage: s = f + c ; s Scalar field f+c on the 2-dimensional differentiable manifold M sage: s.display() f+c: M --> R on U: (x, y) |--> (a*x^2 + a*y^2 + a + 1)/(x^2 + y^2 + 1) on V: (u, v) |--> ((a + 1)*u^2 + (a + 1)*v^2 + a)/(u^2 + v^2 + 1)
and subtracted::
sage: s = f - c ; s Scalar field f-c on the 2-dimensional differentiable manifold M sage: s.display() f-c: M --> R on U: (x, y) |--> -(a*x^2 + a*y^2 + a - 1)/(x^2 + y^2 + 1) on V: (u, v) |--> -((a - 1)*u^2 + (a - 1)*v^2 + a)/(u^2 + v^2 + 1)
Some tests::
sage: f + zer == f True sage: f - f == zer True sage: f + (-f) == zer True sage: (f+c)-f == c True sage: (f-c)+c == f True
We may add a number (interpreted as a constant scalar field) to a scalar field::
sage: s = f + 1 ; s Scalar field on the 2-dimensional differentiable manifold M sage: s.display() M --> R on U: (x, y) |--> (x^2 + y^2 + 2)/(x^2 + y^2 + 1) on V: (u, v) |--> (2*u^2 + 2*v^2 + 1)/(u^2 + v^2 + 1) sage: (f+1)-1 == f True
The number can represented by a symbolic variable::
sage: s = a + f ; s Scalar field on the 2-dimensional differentiable manifold M sage: s == c + f True
However if the symbolic variable is a chart coordinate, the addition is performed only on the chart domain::
sage: s = f + x; s Scalar field on the 2-dimensional differentiable manifold M sage: s.display() M --> R on U: (x, y) |--> (x^3 + x*y^2 + x + 1)/(x^2 + y^2 + 1) sage: s = f + u; s Scalar field on the 2-dimensional differentiable manifold M sage: s.display() M --> R on V: (u, v) |--> (u^3 + (u + 1)*v^2 + u^2 + u)/(u^2 + v^2 + 1)
The addition of two scalar fields with different domains is possible if the domain of one of them is a subset of the domain of the other; the domain of the result is then this subset::
sage: f.domain() 2-dimensional differentiable manifold M sage: g.domain() Open subset U of the 2-dimensional differentiable manifold M sage: s = f + g ; s Scalar field on the Open subset U of the 2-dimensional differentiable manifold M sage: s.domain() Open subset U of the 2-dimensional differentiable manifold M sage: s.display() U --> R (x, y) |--> (x*y^3 + (x^3 + x)*y + 1)/(x^2 + y^2 + 1) on W: (u, v) |--> (u^6 + 3*u^4*v^2 + 3*u^2*v^4 + v^6 + u*v^3 + (u^3 + u)*v)/(u^6 + v^6 + (3*u^2 + 1)*v^4 + u^4 + (3*u^4 + 2*u^2)*v^2)
The operation actually performed is `f|_U + g`::
sage: s == f.restrict(U) + g True
In Sage framework, the addition of `f` and `g` is permitted because there is a *coercion* of the parent of `f`, namely `C^k(M)`, to the parent of `g`, namely `C^k(U)` (see :class:`~sage.manifolds.differentiable.scalarfield_algebra.DiffScalarFieldAlgebra`)::
sage: CM = M.scalar_field_algebra() sage: CU = U.scalar_field_algebra() sage: CU.has_coerce_map_from(CM) True
The coercion map is nothing but the restriction to domain `U`::
sage: CU.coerce(f) == f.restrict(U) True
Since the algebra `C^k(M)` is a vector space over `\RR`, scalar fields can be multiplied by a number, either an explicit one::
sage: s = 2*f ; s Scalar field on the 2-dimensional differentiable manifold M sage: s.display() M --> R on U: (x, y) |--> 2/(x^2 + y^2 + 1) on V: (u, v) |--> 2*(u^2 + v^2)/(u^2 + v^2 + 1)
or a symbolic one::
sage: s = a*f ; s Scalar field on the 2-dimensional differentiable manifold M sage: s.display() M --> R on U: (x, y) |--> a/(x^2 + y^2 + 1) on V: (u, v) |--> (u^2 + v^2)*a/(u^2 + v^2 + 1)
However, if the symbolic variable is a chart coordinate, the multiplication is performed only in the corresponding chart::
sage: s = x*f; s Scalar field on the 2-dimensional differentiable manifold M sage: s.display() M --> R on U: (x, y) |--> x/(x^2 + y^2 + 1) sage: s = u*f; s Scalar field on the 2-dimensional differentiable manifold M sage: s.display() M --> R on V: (u, v) |--> (u^2 + v^2)*u/(u^2 + v^2 + 1)
Some tests::
sage: 0*f == 0 True sage: 0*f == zer True sage: 1*f == f True sage: (-2)*f == - f - f True
The ring multiplication of the algebras `C^k(M)` and `C^k(U)` is the pointwise multiplication of functions::
sage: s = f*f ; s Scalar field f*f on the 2-dimensional differentiable manifold M sage: s.display() f*f: M --> R on U: (x, y) |--> 1/(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1) on V: (u, v) |--> (u^4 + 2*u^2*v^2 + v^4)/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1) sage: s = g*h ; s Scalar field g*h on the Open subset U of the 2-dimensional differentiable manifold M sage: s.display() g*h: U --> R (x, y) |--> x*y*H(x, y) on W: (u, v) |--> u*v*H(u/(u^2 + v^2), v/(u^2 + v^2))/(u^4 + 2*u^2*v^2 + v^4)
Thanks to the coercion `C^k(M)\rightarrow C^k(U)` mentionned above, it is possible to multiply a scalar field defined on `M` by a scalar field defined on `U`, the result being a scalar field defined on `U`::
sage: f.domain(), g.domain() (2-dimensional differentiable manifold M, Open subset U of the 2-dimensional differentiable manifold M) sage: s = f*g ; s Scalar field on the Open subset U of the 2-dimensional differentiable manifold M sage: s.display() U --> R (x, y) |--> x*y/(x^2 + y^2 + 1) on W: (u, v) |--> u*v/(u^4 + v^4 + (2*u^2 + 1)*v^2 + u^2) sage: s == f.restrict(U)*g True
Scalar fields can be divided (pointwise division)::
sage: s = f/c ; s Scalar field f/c on the 2-dimensional differentiable manifold M sage: s.display() f/c: M --> R on U: (x, y) |--> 1/(a*x^2 + a*y^2 + a) on V: (u, v) |--> (u^2 + v^2)/(a*u^2 + a*v^2 + a) sage: s = g/h ; s Scalar field g/h on the Open subset U of the 2-dimensional differentiable manifold M sage: s.display() g/h: U --> R (x, y) |--> x*y/H(x, y) on W: (u, v) |--> u*v/((u^4 + 2*u^2*v^2 + v^4)*H(u/(u^2 + v^2), v/(u^2 + v^2))) sage: s = f/g ; s Scalar field on the Open subset U of the 2-dimensional differentiable manifold M sage: s.display() U --> R (x, y) |--> 1/(x*y^3 + (x^3 + x)*y) on W: (u, v) |--> (u^6 + 3*u^4*v^2 + 3*u^2*v^4 + v^6)/(u*v^3 + (u^3 + u)*v) sage: s == f.restrict(U)/g True
For scalar fields defined on a single chart domain, we may perform some arithmetics with symbolic expressions involving the chart coordinates::
sage: s = g + x^2 - y ; s Scalar field on the Open subset U of the 2-dimensional differentiable manifold M sage: s.display() U --> R (x, y) |--> x^2 + (x - 1)*y on W: (u, v) |--> -(v^3 - u^2 + (u^2 - u)*v)/(u^4 + 2*u^2*v^2 + v^4)
::
sage: s = g*x ; s Scalar field on the Open subset U of the 2-dimensional differentiable manifold M sage: s.display() U --> R (x, y) |--> x^2*y on W: (u, v) |--> u^2*v/(u^6 + 3*u^4*v^2 + 3*u^2*v^4 + v^6)
::
sage: s = g/x ; s Scalar field on the Open subset U of the 2-dimensional differentiable manifold M sage: s.display() U --> R (x, y) |--> y on W: (u, v) |--> v/(u^2 + v^2) sage: s = x/g ; s Scalar field on the Open subset U of the 2-dimensional differentiable manifold M sage: s.display() U --> R (x, y) |--> 1/y on W: (u, v) |--> (u^2 + v^2)/v
The test suite is passed::
sage: TestSuite(f).run() sage: TestSuite(zer).run()
""" latex_name=None): r""" Construct a scalar field.
TESTS::
sage: M = Manifold(2, 'M') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x+y}, name='f') ; f Scalar field f on the 2-dimensional differentiable manifold M sage: from sage.manifolds.scalarfield import ScalarField sage: isinstance(f, ScalarField) True sage: f.parent() Algebra of differentiable scalar fields on the 2-dimensional differentiable manifold M sage: TestSuite(f).run()
""" chart=chart, name=name, latex_name=latex_name)
####### Required methods for an algebra element (beside arithmetic) #######
r""" Initialize the derived quantities.
TESTS::
sage: M = Manifold(2, 'M') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x+y}) sage: f._init_derived()
"""
r""" Delete the derived quantities.
TESTS::
sage: M = Manifold(2, 'M') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x+y}) sage: U = M.open_subset('U', coord_def={X: x>0}) sage: f.restrict(U) Scalar field on the Open subset U of the 2-dimensional differentiable manifold M sage: f._restrictions {Open subset U of the 2-dimensional differentiable manifold M: Scalar field on the Open subset U of the 2-dimensional differentiable manifold M} sage: f._del_derived() sage: f._restrictions # restrictions are derived quantities {}
""" # First deletes any reference to self in the vectors' dictionaries: # Then clears the dictionary of Lie derivatives
r""" Return the tensor type of ``self``, when the latter is considered as a tensor field on the manifold. This is always `(0, 0)`.
OUTPUT:
- always `(0, 0)`
EXAMPLES::
sage: M = Manifold(2, 'M') sage: c_xy.<x,y> = M.chart() sage: f = M.scalar_field(x+2*y) sage: f.tensor_type() (0, 0)
"""
r""" Return the differential of ``self``.
OUTPUT:
- a :class:`~sage.manifolds.differentiable.diff_form.DiffForm` (or of :class:`~sage.manifolds.differentiable.diff_form.DiffFormParal` if the scalar field's domain is parallelizable) representing the 1-form that is the differential of the scalar field
EXAMPLES:
Differential of a scalar field on a 3-dimensional differentiable manifold::
sage: M = Manifold(3, 'M') sage: c_xyz.<x,y,z> = M.chart() sage: f = M.scalar_field(cos(x)*z^3 + exp(y)*z^2, name='f') sage: df = f.differential() ; df 1-form df on the 3-dimensional differentiable manifold M sage: df.display() df = -z^3*sin(x) dx + z^2*e^y dy + (3*z^2*cos(x) + 2*z*e^y) dz sage: latex(df) \mathrm{d}f sage: df.parent() Free module Omega^1(M) of 1-forms on the 3-dimensional differentiable manifold M
The result is cached, i.e. is not recomputed unless ``f`` is changed::
sage: f.differential() is df True
Since the exterior derivative of a scalar field (considered a 0-form) is nothing but its differential, ``exterior_derivative()`` is an alias of ``differential()``::
sage: df = f.exterior_derivative() ; df 1-form df on the 3-dimensional differentiable manifold M sage: df.display() df = -z^3*sin(x) dx + z^2*e^y dy + (3*z^2*cos(x) + 2*z*e^y) dz sage: latex(df) \mathrm{d}f
One may also use the function :func:`~sage.manifolds.utilities.exterior_derivative` or its alias :func:`~sage.manifolds.utilities.xder` instead of the method ``exterior_derivative()``::
sage: from sage.manifolds.utilities import xder sage: xder(f) is f.exterior_derivative() True
Differential computed on a chart that is not the default one::
sage: c_uvw.<u,v,w> = M.chart() sage: g = M.scalar_field(u*v^2*w^3, c_uvw, name='g') sage: dg = g.differential() ; dg 1-form dg on the 3-dimensional differentiable manifold M sage: dg._components {Coordinate frame (M, (d/du,d/dv,d/dw)): 1-index components w.r.t. Coordinate frame (M, (d/du,d/dv,d/dw))} sage: dg.comp(c_uvw.frame())[:, c_uvw] [v^2*w^3, 2*u*v*w^3, 3*u*v^2*w^2] sage: dg.display(c_uvw.frame(), c_uvw) dg = v^2*w^3 du + 2*u*v*w^3 dv + 3*u*v^2*w^2 dw
The exterior derivative is nilpotent::
sage: ddf = df.exterior_derivative() ; ddf 2-form ddf on the 3-dimensional differentiable manifold M sage: ddf == 0 True sage: ddf[:] # for the incredule [0 0 0] [0 0 0] [0 0 0] sage: ddg = dg.exterior_derivative() ; ddg 2-form ddg on the 3-dimensional differentiable manifold M sage: ddg == 0 True
""" format_unop_latex) # A new computation is necessary: latex_name=rlname) for chart in self._domain._atlas: self._differential.add_comp(chart._frame) # since a newly # created set of components is zero else:
r""" Compute the Lie derivative with respect to a vector field.
In the present case (scalar field), the Lie derivative is equal to the scalar field resulting from the action of the vector field on the scalar field.
INPUT:
- ``vector`` -- vector field with respect to which the Lie derivative is to be taken
OUTPUT:
- the scalar field that is the Lie derivative of the scalar field with respect to ``vector``
EXAMPLES:
Lie derivative on a 2-dimensional manifold::
sage: M = Manifold(2, 'M') sage: c_xy.<x,y> = M.chart() sage: f = M.scalar_field(x^2*cos(y)) sage: v = M.vector_field(name='v') sage: v[:] = (-y, x) sage: f.lie_derivative(v) Scalar field on the 2-dimensional differentiable manifold M sage: f.lie_derivative(v).expr() -x^3*sin(y) - 2*x*y*cos(y)
The result is cached::
sage: f.lie_derivative(v) is f.lie_derivative(v) True
An alias is ``lie_der``::
sage: f.lie_der(v) is f.lie_derivative(v) True
Alternative expressions of the Lie derivative of a scalar field::
sage: f.lie_der(v) == v(f) # the vector acting on f True sage: f.lie_der(v) == f.differential()(v) # the differential of f acting on the vector True
A vanishing Lie derivative::
sage: f.set_expr(x^2 + y^2) sage: f.lie_der(v).display() M --> R (x, y) |--> 0
""" # The Lie derivative is cached in _lie_derivatives if neither # the scalar field nor ``vector`` have been modified. # A new computation must be performed
r""" Compute the Hodge dual of the scalar field with respect to some metric.
If `M` is the domain of the scalar field (denoted by `f`), `n` is the dimension of `M` and `g` is a pseudo-Riemannian metric on `M`, the *Hodge dual* of `f` w.r.t. `g` is the `n`-form `*f` defined by
.. MATH::
*f = f \epsilon,
where `\epsilon` is the volume `n`-form associated with `g` (see :meth:`~sage.manifolds.differentiable.metric.PseudoRiemannianMetric.volume_form`).
INPUT:
- ``metric`` -- a pseudo-Riemannian metric defined on the same manifold as the current scalar field; must be an instance of :class:`~sage.manifolds.differentiable.metric.PseudoRiemannianMetric`
OUTPUT:
- the `n`-form `*f`
EXAMPLES:
Hodge dual of a scalar field in the Euclidean space `R^3`::
sage: M = Manifold(3, 'M', start_index=1) sage: X.<x,y,z> = M.chart() sage: g = M.metric('g') sage: g[1,1], g[2,2], g[3,3] = 1, 1, 1 sage: f = M.scalar_field(function('F')(x,y,z), name='f') sage: sf = f.hodge_dual(g) ; sf 3-form *f on the 3-dimensional differentiable manifold M sage: sf.display() *f = F(x, y, z) dx/\dy/\dz sage: ssf = sf.hodge_dual(g) ; ssf Scalar field **f on the 3-dimensional differentiable manifold M sage: ssf.display() **f: M --> R (x, y, z) |--> F(x, y, z) sage: ssf == f # must hold for a Riemannian metric True
Instead of calling the method :meth:`hodge_dual` on the scalar field, one can invoke the method :meth:`~sage.manifolds.differentiable.metric.PseudoRiemannianMetric.hodge_star` of the metric::
sage: f.hodge_dual(g) == g.hodge_star(f) True
"""
r""" Return the Schouten-Nijenhuis bracket of ``self``, considered as a multivector field of degree 0, with a multivector field.
See :meth:`~sage.manifolds.differentiable.multivectorfield.MultivectorFieldParal.bracket` for details.
INPUT:
- ``other`` -- a multivector field of degree `p`
OUTPUT:
- if `p=0`, a zero scalar field - if `p=1`, an instance of :class:`DiffScalarField` representing the Schouten-Nijenhuis bracket ``[self,other]`` - if `p\geq 2`, an instance of :class:`~sage.manifolds.differentiable.multivectorfield.MultivectorField` representing the Schouten-Nijenhuis bracket ``[self,other]``
EXAMPLES:
The Schouten-Nijenhuis bracket of two scalar fields is identically zero::
sage: M = Manifold(2, 'M') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x+y^2}, name='f') sage: g = M.scalar_field({X: y-x}, name='g') sage: s = f.bracket(g); s Scalar field zero on the 2-dimensional differentiable manifold M sage: s.display() zero: M --> R (x, y) |--> 0
while the Schouten-Nijenhuis bracket of a scalar field `f` with a multivector field `a` is equal to minus the interior product of the differential of `f` with `a`::
sage: a = M.multivector_field(2, name='a') sage: a[0,1] = x*y ; a.display() a = x*y d/dx/\d/dy sage: s = f.bracket(a); s Vector field -i_df a on the 2-dimensional differentiable manifold M sage: s.display() -i_df a = 2*x*y^2 d/dx - x*y d/dy
See :meth:`~sage.manifolds.differentiable.multivectorfield.MultivectorFieldParal.bracket` for other examples.
"""
r""" Return the exterior product of ``self``, considered as a differential form of degree 0 or a multivector field of degree 0, with ``other``.
See :meth:`~sage.manifolds.differentiable.diff_form.DiffFormParal.wedge` (exterior product of differential forms) or :meth:`~sage.manifolds.differentiable.multivectorfield.MultivectorFieldParal.wedge` (exterior product of multivector fields) for details.
For a scalar field `f` and a `p`-form (or `p`-vector field) `a`, the exterior product reduces to the standard product on the left by an element of the base ring of the module of `p`-forms (or `p`-vector fields): `f\wedge a = f a`.
INPUT:
- ``other`` -- a differential form or a multivector field `a`
OUTPUT:
- the product `f a`, where `f` is ``self``
EXAMPLES::
sage: M = Manifold(2, 'M') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x+y^2}, name='f') sage: a = M.diff_form(2, name='a') sage: a[0,1] = x*y sage: s = f.wedge(a); s 2-form on the 2-dimensional differentiable manifold M sage: s.display() (x*y^3 + x^2*y) dx/\dy
"""
r""" Return the degree of ``self``, considered as a differential form or a multivector field, i.e. zero.
This trivial method is provided for consistency with the exterior calculus scheme, cf. the methods :meth:`~sage.manifolds.differentiable.diff_form.DiffForm.degree` (differential forms) and :meth:`~sage.manifolds.differentiable.multivectorfield.MultivectorField.degree` (multivector fields).
OUTPUT:
- 0
EXAMPLES::
sage: M = Manifold(2, 'M') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x+y^2}) sage: f.degree() 0
"""
r""" Return the gradient of ``self`` (with respect to a given metric).
The *gradient* of a scalar field `f` with respect to a metric `g` is the vector field `\mathrm{grad}\, f` whose components in any coordinate frame are
.. MATH::
(\mathrm{grad}\, f)^i = g^{ij} \frac{\partial F}{\partial x^j}
where the `x^j`'s are the coordinates with respect to which the frame is defined and `F` is the chart function representing `f` in these coordinates: `f(p) = F(x^1(p),\ldots,x^n(p))` for any point `p` in the chart domain. In other words, the gradient of `f` is the vector field that is the `g`-dual of the differential of `f`.
INPUT:
- ``metric`` -- (default: ``None``) the pseudo-Riemannian metric `g` involved in the definition of the gradient; if none is provided, the domain of ``self`` is supposed to be endowed with a default metric (i.e. is supposed to be pseudo-Riemannian manifold, see :class:`~sage.manifolds.differentiable.pseudo_riemannian.PseudoRiemannianManifold`) and the latter is used to define the gradient
OUTPUT:
- instance of :class:`~sage.manifolds.differentiable.vectorfield.VectorField` representing the gradient of ``self``
EXAMPLES:
Gradient of a scalar field in the Euclidean plane::
sage: M = Manifold(2, 'M', structure='Riemannian') sage: X.<x,y> = M.chart() sage: g = M.metric() sage: g[0,0], g[1,1] = 1, 1 sage: f = M.scalar_field(cos(x*y), name='f') sage: v = f.gradient(); v Vector field grad(f) on the 2-dimensional Riemannian manifold M sage: v.display() grad(f) = -y*sin(x*y) d/dx - x*sin(x*y) d/dy
The function :func:`~sage.manifolds.operators.grad` from the :mod:`~sage.manifolds.operators` module can be used instead of the method :meth:`gradient`::
sage: from sage.manifolds.operators import grad sage: grad(f) == f.gradient() True
The gradient can be taken with respect to a metric tensor that is not the default one::
sage: h = M.lorentzian_metric('h') sage: h[0,0], h[1,1] = -1, 1/(1+x^2+y^2) sage: h.display() h = -dx*dx + 1/(x^2 + y^2 + 1) dy*dy sage: v = f.gradient(h); v Vector field grad_h(f) on the 2-dimensional Riemannian manifold M sage: v.display() grad_h(f) = y*sin(x*y) d/dx - (x^3 + x*y^2 + x)*sin(x*y) d/dy
""" self._latex_name + r"\right)" else: r"}\left(" + self._latex_name + r"\right)" # The name is propagated to possible restrictions of self:
r""" Return the Laplacian of ``self`` with respect to a given metric (Laplace-Beltrami operator).
The *Laplacian* of a scalar field `f` with respect to a metric `g` is the scalar field
.. MATH::
\Delta f = g^{ij} \nabla_i \nabla_j f = \nabla_i \nabla^i f
where `\nabla` is the Levi-Civita connection of `g`. `\Delta` is also called the *Laplace-Beltrami operator*.
INPUT:
- ``metric`` -- (default: ``None``) the pseudo-Riemannian metric `g` involved in the definition of the Laplacian; if none is provided, the domain of ``self`` is supposed to be endowed with a default metric (i.e. is supposed to be pseudo-Riemannian manifold, see :class:`~sage.manifolds.differentiable.pseudo_riemannian.PseudoRiemannianManifold`) and the latter is used to define the Laplacian
OUTPUT:
- instance of :class:`DiffScalarField` representing the Laplacian of ``self``
EXAMPLES:
Laplacian of a scalar field on the Euclidean plane::
sage: M = Manifold(2, 'M', structure='Riemannian') sage: X.<x,y> = M.chart() sage: g = M.metric() sage: g[0,0], g[1,1] = 1, 1 sage: f = M.scalar_field(function('F')(x,y), name='f') sage: s = f.laplacian(); s Scalar field Delta(f) on the 2-dimensional Riemannian manifold M sage: s.display() Delta(f): M --> R (x, y) |--> d^2(F)/dx^2 + d^2(F)/dy^2
The function :func:`~sage.manifolds.operators.laplacian` from the :mod:`~sage.manifolds.operators` module can be used instead of the method :meth:`laplacian`::
sage: from sage.manifolds.operators import laplacian sage: laplacian(f) == s True
The Laplacian can be taken with respect to a metric tensor that is not the default one::
sage: h = M.lorentzian_metric('h') sage: h[0,0], h[1,1] = -1, 1/(1+x^2+y^2) sage: s = f.laplacian(h); s Scalar field Delta_h(f) on the 2-dimensional Riemannian manifold M sage: s.display() Delta_h(f): M --> R (x, y) |--> (y^4*d^2(F)/dy^2 + y^3*d(F)/dy + (2*(x^2 + 1)*d^2(F)/dy^2 - d^2(F)/dx^2)*y^2 + (x^2 + 1)*y*d(F)/dy + x*d(F)/dx - (x^2 + 1)*d^2(F)/dx^2 + (x^4 + 2*x^2 + 1)*d^2(F)/dy^2)/(x^2 + y^2 + 1)
The Laplacian of `f` is equal to the divergence of the gradient of `f`:
.. MATH::
\Delta f = \mathrm{div}( \mathrm{grad}\, f )
Let us check this formula::
sage: s == f.gradient(h).div(h) True
""" r"\right)" else: r"}\left(" + self._latex_name + r"\right)" # The name is propagated to possible restrictions of self:
r""" Return the d'Alembertian of ``self`` with respect to a given Lorentzian metric.
The *d'Alembertian* of a scalar field `f` with respect to a Lorentzian metric `g` is nothing but the Laplacian (see :meth:`laplacian`) of `f` with respect to that metric:
.. MATH::
\Box f = g^{ij} \nabla_i \nabla_j f = \nabla_i \nabla^i f
where `\nabla` is the Levi-Civita connection of `g`.
.. NOTE::
If the metric `g` is not Lorentzian, the name *d'Alembertian* is not appropriate and one should use :meth:`laplacian` instead.
INPUT:
- ``metric`` -- (default: ``None``) the Lorentzian metric `g` involved in the definition of the d'Alembertian; if none is provided, the domain of ``self`` is supposed to be endowed with a default Lorentzian metric (i.e. is supposed to be Lorentzian manifold, see :class:`~sage.manifolds.differentiable.pseudo_riemannian.PseudoRiemannianManifold`) and the latter is used to define the d'Alembertian
OUTPUT:
- instance of :class:`DiffScalarField` representing the d'Alembertian of ``self``
EXAMPLES:
d'Alembertian of a scalar field in Minkowski spacetime::
sage: M = Manifold(4, 'M', structure='Lorentzian') sage: X.<t,x,y,z> = M.chart() sage: g = M.metric() sage: g[0,0], g[1,1], g[2,2], g[3,3] = -1, 1, 1, 1 sage: f = M.scalar_field(t + x^2 + t^2*y^3 - x*z^4, name='f') sage: s = f.dalembertian(); s Scalar field Box(f) on the 4-dimensional Lorentzian manifold M sage: s.display() Box(f): M --> R (t, x, y, z) |--> 6*t^2*y - 2*y^3 - 12*x*z^2 + 2
The function :func:`~sage.manifolds.operators.dalembertian` from the :mod:`~sage.manifolds.operators` module can be used instead of the method :meth:`dalembertian`::
sage: from sage.manifolds.operators import dalembertian sage: dalembertian(f) == s True
""" raise TypeError("the {} is not a Lorentzian ".format(metric) + "metric; use laplacian() instead") r"\right)" else: resu._name = "Box_{}({})".format(metric._name, self._name) resu._latex_name = r"\Box_{" + metric._latex_name + \ r"}\left(" + self._latex_name + r"\right)" # The name is propagated to possible restrictions of self: restrict.set_name(resu._name, latex_name=resu._latex_name) |