Scalar Fields#
Given a topological manifold \(M\) over a topological field \(K\) (in most applications, \(K = \RR\) or \(K = \CC\)), a scalar field on \(M\) is a continuous map
Scalar fields are implemented by the class ScalarField
.
AUTHORS:
Eric Gourgoulhon, Michal Bejger (2013-2015): initial version
Travis Scrimshaw (2016): review tweaks
Marco Mancini (2017): SymPy as an optional symbolic engine, alternative to SR
Florentin Jaffredo (2018) : series expansion with respect to a given parameter
Michael Jung (2019) : improve restrictions; make
display()
show all distinct expressions
REFERENCES:
- class sage.manifolds.scalarfield.ScalarField(parent, coord_expression=None, chart=None, name=None, latex_name=None)[source]#
Bases:
CommutativeAlgebraElement
,ModuleElementWithMutability
Scalar field on a topological manifold.
Given a topological manifold \(M\) over a topological field \(K\) (in most applications, \(K = \RR\) or \(K = \CC\)), a scalar field on \(M\) is a continuous map
\[f: M \longrightarrow K.\]A scalar field on \(M\) is an element of the commutative algebra \(C^0(M)\) (see
ScalarFieldAlgebra
).INPUT:
parent
– the algebra of scalar fields containing the scalar field (must be an instance of classScalarFieldAlgebra
)coord_expression
– (default:None
) coordinate expression(s) of the scalar field; this can be eithera 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 argumentchart
chart
– (default:None
) chart defining the coordinates used incoord_expression
when the latter is a single coordinate expression; if none is provided (default), the default chart of the open set is assumed. Ifchart=='all'
,coord_expression
is assumed to be independent of the chart (constant scalar field).name
– (default:None
) string; name (symbol) given to the scalar fieldlatex_name
– (default:None
) string; LaTeX symbol to denote the scalar field; if none is provided, the LaTeX symbol is set toname
If
coord_expression
isNone
or incomplete, coordinate expressions can be added after the creation of the object, by means of the methodsadd_expr()
,add_expr_by_continuation()
andset_expr()
.EXAMPLES:
A scalar field on the 2-sphere:
sage: M = Manifold(2, 'M', structure='topological') # 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 topological manifold M sage: f.display() f: M → ℝ on U: (x, y) ↦ 1/(x^2 + y^2 + 1) on V: (u, v) ↦ (u^2 + v^2)/(u^2 + v^2 + 1)
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') # the 2-dimensional sphere S^2 >>> U = M.open_subset('U') # complement of the North pole >>> c_xy = U.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2)# stereographic coordinates from the North pole >>> V = M.open_subset('V') # complement of the South pole >>> c_uv = V.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2)# stereographic coordinates from the South pole >>> M.declare_union(U,V) # S^2 is the union of U and V >>> xy_to_uv = c_xy.transition_map(c_uv, (x/(x**Integer(2)+y**Integer(2)), y/(x**Integer(2)+y**Integer(2))), ... intersection_name='W', ... restrictions1= x**Integer(2)+y**Integer(2)!=Integer(0), ... restrictions2= u**Integer(2)+v**Integer(2)!=Integer(0)) >>> uv_to_xy = xy_to_uv.inverse() >>> f = M.scalar_field({c_xy: Integer(1)/(Integer(1)+x**Integer(2)+y**Integer(2)), c_uv: (u**Integer(2)+v**Integer(2))/(Integer(1)+u**Integer(2)+v**Integer(2))}, ... name='f') ; f Scalar field f on the 2-dimensional topological manifold M >>> f.display() f: M → ℝ 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 topological manifold M
>>> from sage.all import * >>> g = U.scalar_field(x*y, chart=c_xy, name='g') ; g Scalar field g on the Open subset U of the 2-dimensional topological 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 topological manifold M
>>> from sage.all import * >>> g = U.scalar_field({c_xy: x*y}, name='g') ; g Scalar field g on the Open subset U of the 2-dimensional topological manifold M
Since
c_xy
is the default chart ofU
, the argumentchart
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 topological manifold M
>>> from sage.all import * >>> g = U.scalar_field(x*y, name='g') ; g Scalar field g on the Open subset U of the 2-dimensional topological 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 → ℝ (x, y) ↦ x*y on W: (u, v) ↦ u*v/(u^4 + 2*u^2*v^2 + v^4)
>>> from sage.all import * >>> g.display() g: U → ℝ (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 topological manifold M
>>> from sage.all import * >>> f = M.scalar_field(Integer(1)/(Integer(1)+x**Integer(2)+y**Integer(2)), chart=c_xy, name='f') ; f Scalar field f on the 2-dimensional topological manifold M
Their definition must then be completed by providing the expressions on other charts, via the method
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 → ℝ on U: (x, y) ↦ 1/(x^2 + y^2 + 1) on V: (u, v) ↦ (u^2 + v^2)/(u^2 + v^2 + 1)
>>> from sage.all import * >>> f.add_expr((u**Integer(2)+v**Integer(2))/(Integer(1)+u**Integer(2)+v**Integer(2)), chart=c_uv) >>> f.display() f: M → ℝ 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 → ℝ on U: (x, y) ↦ 1/(x^2 + y^2 + 1) on V: (u, v) ↦ (u^2 + v^2)/(u^2 + v^2 + 1)
>>> from sage.all import * >>> f = M.scalar_field(name='f') >>> f.add_expr(Integer(1)/(Integer(1)+x**Integer(2)+y**Integer(2)), chart=c_xy) >>> f.add_expr((u**Integer(2)+v**Integer(2))/(Integer(1)+u**Integer(2)+v**Integer(2)), chart=c_uv) >>> f.display() f: M → ℝ 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
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 topological manifold M sage: f.add_expr_by_continuation(c_uv, U.intersection(V)) sage: f.display() f: M → ℝ on U: (x, y) ↦ 1/(x^2 + y^2 + 1) on V: (u, v) ↦ (u^2 + v^2)/(u^2 + v^2 + 1)
>>> from sage.all import * >>> f = M.scalar_field(Integer(1)/(Integer(1)+x**Integer(2)+y**Integer(2)), chart=c_xy, name='f') ; f Scalar field f on the 2-dimensional topological manifold M >>> f.add_expr_by_continuation(c_uv, U.intersection(V)) >>> f.display() f: M → ℝ 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 topological manifold M sage: h.display() h: U → ℝ (x, y) ↦ H(x, y) on W: (u, v) ↦ H(u/(u^2 + v^2), v/(u^2 + v^2))
>>> from sage.all import * >>> h = U.scalar_field(function('H')(x, y), name='h') ; h Scalar field h on the Open subset U of the 2-dimensional topological manifold M >>> h.display() h: U → ℝ (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 fromname
: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}
>>> from sage.all import * >>> latex(f) f >>> f = M.scalar_field({c_xy: Integer(1)/(Integer(1)+x**Integer(2)+y**Integer(2)), c_uv: (u**Integer(2)+v**Integer(2))/(Integer(1)+u**Integer(2)+v**Integer(2))}, ... name='f', latex_name=r'\mathcal{F}') >>> latex(f) \mathcal{F}
The coordinate expression in a given chart is obtained via the method
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)) <class 'sage.symbolic.expression.Expression'>
>>> from sage.all import * >>> f.expr(c_uv) (u^2 + v^2)/(u^2 + v^2 + 1) >>> type(f.expr(c_uv)) <class 'sage.symbolic.expression.Expression'>
The method
coord_function()
returns instead a function of the chart coordinates, i.e. an instance ofChartFunction
: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)
>>> from sage.all import * >>> f.coord_function(c_uv) (u^2 + v^2)/(u^2 + v^2 + 1) >>> type(f.coord_function(c_uv)) <class 'sage.manifolds.chart_func.ChartFunctionRing_with_category.element_class'> >>> f.coord_function(c_uv).display() (u, v) ↦ (u^2 + v^2)/(u^2 + v^2 + 1)
The value returned by the method
expr()
is actually the coordinate expression of the chart function:sage: f.expr(c_uv) is f.coord_function(c_uv).expr() True
>>> from sage.all import * >>> 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 topological manifold M sage: c.display() c: M → ℝ on U: (x, y) ↦ 2 on V: (u, v) ↦ 2
>>> from sage.all import * >>> c = M.scalar_field(Integer(2), chart='all', name='c') ; c Scalar field c on the 2-dimensional topological manifold M >>> c.display() c: M → ℝ on U: (x, y) ↦ 2 on V: (u, v) ↦ 2
A shortcut is to use the method
constant_scalar_field()
:sage: c == M.constant_scalar_field(2) True
>>> from sage.all import * >>> c == M.constant_scalar_field(Integer(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 topological manifold M sage: c.display() c: M → ℝ on U: (x, y) ↦ a on V: (u, v) ↦ a
>>> from sage.all import * >>> var('a') a >>> c = M.constant_scalar_field(a, name='c') ; c Scalar field c on the 2-dimensional topological manifold M >>> c.display() c: M → ℝ 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 topological manifold M sage: zer.display() zero: M → ℝ on U: (x, y) ↦ 0 on V: (u, v) ↦ 0
>>> from sage.all import * >>> zer = M.constant_scalar_field(Integer(0)) ; zer Scalar field zero on the 2-dimensional topological manifold M >>> zer.display() zero: M → ℝ on U: (x, y) ↦ 0 on V: (u, v) ↦ 0
It can be obtained directly by means of the function
zero_scalar_field()
:sage: zer is M.zero_scalar_field() True
>>> from sage.all import * >>> zer is M.zero_scalar_field() True
A third way is to get it as the zero element of the algebra \(C^0(M)\) of scalar fields on \(M\) (see below):
sage: zer is M.scalar_field_algebra().zero() True
>>> from sage.all import * >>> zer is M.scalar_field_algebra().zero() True
The constant scalar fields zero and one are immutable, and therefore their expressions cannot be changed:
sage: zer.is_immutable() True sage: zer.set_expr(x) Traceback (most recent call last): ... ValueError: the expressions of an immutable element cannot be changed sage: one = M.one_scalar_field() sage: one.is_immutable() True sage: one.set_expr(x) Traceback (most recent call last): ... ValueError: the expressions of an immutable element cannot be changed
>>> from sage.all import * >>> zer.is_immutable() True >>> zer.set_expr(x) Traceback (most recent call last): ... ValueError: the expressions of an immutable element cannot be changed >>> one = M.one_scalar_field() >>> one.is_immutable() True >>> one.set_expr(x) Traceback (most recent call last): ... ValueError: the expressions of an immutable element cannot be changed
Other scalar fields can be declared immutable, too:
sage: c.is_immutable() False sage: c.set_immutable() sage: c.is_immutable() True sage: c.set_expr(y^2) Traceback (most recent call last): ... ValueError: the expressions of an immutable element cannot be changed sage: c.set_name('b') Traceback (most recent call last): ... ValueError: the name of an immutable element cannot be changed
>>> from sage.all import * >>> c.is_immutable() False >>> c.set_immutable() >>> c.is_immutable() True >>> c.set_expr(y**Integer(2)) Traceback (most recent call last): ... ValueError: the expressions of an immutable element cannot be changed >>> c.set_name('b') Traceback (most recent call last): ... ValueError: the name of an immutable element cannot be changed
Immutable elements are hashable and can therefore be used as keys for dictionaries:
sage: {c: 1}[c] 1
>>> from sage.all import * >>> {c: Integer(1)}[c] 1
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
>>> from sage.all import * >>> N = M.point((Integer(0),Integer(0)), chart=c_uv) # the North pole >>> S = M.point((Integer(0),Integer(0)), chart=c_xy) # the South pole >>> E = M.point((Integer(1),Integer(0)), chart=c_xy) # a point at the equator >>> f(N) 0 >>> f(S) 1 >>> f(E) 1/2 >>> h(E) H(1, 0) >>> c(E) a >>> zer(E) 0
A scalar field can be compared to another scalar field:
sage: f == g False
>>> from sage.all import * >>> f == g False
…to a symbolic expression:
sage: f == x*y False sage: g == x*y True sage: c == a True
>>> from sage.all import * >>> f == x*y False >>> g == x*y True >>> c == a True
…to a number:
sage: f == 2 False sage: zer == 0 True
>>> from sage.all import * >>> f == Integer(2) False >>> zer == Integer(0) True
…to anything else:
sage: f == M False
>>> from sage.all import * >>> f == M False
Standard mathematical functions are implemented:
sage: sqrt(f) Scalar field sqrt(f) on the 2-dimensional topological manifold M sage: sqrt(f).display() sqrt(f): M → ℝ 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)
>>> from sage.all import * >>> sqrt(f) Scalar field sqrt(f) on the 2-dimensional topological manifold M >>> sqrt(f).display() sqrt(f): M → ℝ 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 topological manifold M sage: tan(f).display() tan(f): M → ℝ 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))
>>> from sage.all import * >>> tan(f) Scalar field tan(f) on the 2-dimensional topological manifold M >>> tan(f).display() tan(f): M → ℝ 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))
Arithmetics of scalar fields
Scalar fields on \(M\) (resp. \(U\)) belong to the algebra \(C^0(M)\) (resp. \(C^0(U)\)):
sage: f.parent() Algebra of scalar fields on the 2-dimensional topological manifold M sage: f.parent() is M.scalar_field_algebra() True sage: g.parent() Algebra of scalar fields on the Open subset U of the 2-dimensional topological manifold M sage: g.parent() is U.scalar_field_algebra() True
>>> from sage.all import * >>> f.parent() Algebra of scalar fields on the 2-dimensional topological manifold M >>> f.parent() is M.scalar_field_algebra() True >>> g.parent() Algebra of scalar fields on the Open subset U of the 2-dimensional topological manifold M >>> 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 topological manifold M sage: s.display() f+c: M → ℝ 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)
>>> from sage.all import * >>> s = f + c ; s Scalar field f+c on the 2-dimensional topological manifold M >>> s.display() f+c: M → ℝ 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 topological manifold M sage: s.display() f-c: M → ℝ 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)
>>> from sage.all import * >>> s = f - c ; s Scalar field f-c on the 2-dimensional topological manifold M >>> s.display() f-c: M → ℝ 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
>>> from sage.all import * >>> f + zer == f True >>> f - f == zer True >>> f + (-f) == zer True >>> (f+c)-f == c True >>> (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 f+1 on the 2-dimensional topological manifold M sage: s.display() f+1: M → ℝ 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
>>> from sage.all import * >>> s = f + Integer(1) ; s Scalar field f+1 on the 2-dimensional topological manifold M >>> s.display() f+1: M → ℝ 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) >>> (f+Integer(1))-Integer(1) == f True
The number can represented by a symbolic variable:
sage: s = a + f ; s Scalar field on the 2-dimensional topological manifold M sage: s == c + f True
>>> from sage.all import * >>> s = a + f ; s Scalar field on the 2-dimensional topological manifold M >>> 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 topological manifold M sage: s.display() M → ℝ on U: (x, y) ↦ (x^3 + x*y^2 + x + 1)/(x^2 + y^2 + 1) on W: (u, v) ↦ (u^4 + v^4 + u^3 + (2*u^2 + u)*v^2 + u)/(u^4 + v^4 + (2*u^2 + 1)*v^2 + u^2) sage: s = f + u; s Scalar field on the 2-dimensional topological manifold M sage: s.display() M → ℝ on W: (x, y) ↦ (x^3 + (x + 1)*y^2 + x^2 + x)/(x^4 + y^4 + (2*x^2 + 1)*y^2 + x^2) on V: (u, v) ↦ (u^3 + (u + 1)*v^2 + u^2 + u)/(u^2 + v^2 + 1)
>>> from sage.all import * >>> s = f + x; s Scalar field on the 2-dimensional topological manifold M >>> s.display() M → ℝ on U: (x, y) ↦ (x^3 + x*y^2 + x + 1)/(x^2 + y^2 + 1) on W: (u, v) ↦ (u^4 + v^4 + u^3 + (2*u^2 + u)*v^2 + u)/(u^4 + v^4 + (2*u^2 + 1)*v^2 + u^2) >>> s = f + u; s Scalar field on the 2-dimensional topological manifold M >>> s.display() M → ℝ on W: (x, y) ↦ (x^3 + (x + 1)*y^2 + x^2 + x)/(x^4 + y^4 + (2*x^2 + 1)*y^2 + x^2) 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 topological manifold M sage: g.domain() Open subset U of the 2-dimensional topological manifold M sage: s = f + g ; s Scalar field f+g on the Open subset U of the 2-dimensional topological manifold M sage: s.domain() Open subset U of the 2-dimensional topological manifold M sage: s.display() f+g: U → ℝ (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)
>>> from sage.all import * >>> f.domain() 2-dimensional topological manifold M >>> g.domain() Open subset U of the 2-dimensional topological manifold M >>> s = f + g ; s Scalar field f+g on the Open subset U of the 2-dimensional topological manifold M >>> s.domain() Open subset U of the 2-dimensional topological manifold M >>> s.display() f+g: U → ℝ (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
>>> from sage.all import * >>> 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^0(M)\), to the parent of \(g\), namely \(C^0(U)\) (see
ScalarFieldAlgebra
):sage: CM = M.scalar_field_algebra() sage: CU = U.scalar_field_algebra() sage: CU.has_coerce_map_from(CM) True
>>> from sage.all import * >>> CM = M.scalar_field_algebra() >>> CU = U.scalar_field_algebra() >>> 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
>>> from sage.all import * >>> CU.coerce(f) == f.restrict(U) True
Since the algebra \(C^0(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 topological manifold M sage: s.display() M → ℝ on U: (x, y) ↦ 2/(x^2 + y^2 + 1) on V: (u, v) ↦ 2*(u^2 + v^2)/(u^2 + v^2 + 1)
>>> from sage.all import * >>> s = Integer(2)*f ; s Scalar field on the 2-dimensional topological manifold M >>> s.display() M → ℝ 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 topological manifold M sage: s.display() M → ℝ on U: (x, y) ↦ a/(x^2 + y^2 + 1) on V: (u, v) ↦ (u^2 + v^2)*a/(u^2 + v^2 + 1)
>>> from sage.all import * >>> s = a*f ; s Scalar field on the 2-dimensional topological manifold M >>> s.display() M → ℝ 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 topological manifold M sage: s.display() M → ℝ on U: (x, y) ↦ x/(x^2 + y^2 + 1) on W: (u, v) ↦ u/(u^2 + v^2 + 1) sage: s = u*f; s Scalar field on the 2-dimensional topological manifold M sage: s.display() M → ℝ on W: (x, y) ↦ x/(x^4 + y^4 + (2*x^2 + 1)*y^2 + x^2) on V: (u, v) ↦ (u^2 + v^2)*u/(u^2 + v^2 + 1)
>>> from sage.all import * >>> s = x*f; s Scalar field on the 2-dimensional topological manifold M >>> s.display() M → ℝ on U: (x, y) ↦ x/(x^2 + y^2 + 1) on W: (u, v) ↦ u/(u^2 + v^2 + 1) >>> s = u*f; s Scalar field on the 2-dimensional topological manifold M >>> s.display() M → ℝ on W: (x, y) ↦ x/(x^4 + y^4 + (2*x^2 + 1)*y^2 + x^2) 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
>>> from sage.all import * >>> Integer(0)*f == Integer(0) True >>> Integer(0)*f == zer True >>> Integer(1)*f == f True >>> (-Integer(2))*f == - f - f True
The ring multiplication of the algebras \(C^0(M)\) and \(C^0(U)\) is the pointwise multiplication of functions:
sage: s = f*f ; s Scalar field f*f on the 2-dimensional topological manifold M sage: s.display() f*f: M → ℝ 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 topological manifold M sage: s.display() g*h: U → ℝ (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)
>>> from sage.all import * >>> s = f*f ; s Scalar field f*f on the 2-dimensional topological manifold M >>> s.display() f*f: M → ℝ 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) >>> s = g*h ; s Scalar field g*h on the Open subset U of the 2-dimensional topological manifold M >>> s.display() g*h: U → ℝ (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^0(M) \to C^0(U)\) mentioned 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 topological manifold M, Open subset U of the 2-dimensional topological manifold M) sage: s = f*g ; s Scalar field f*g on the Open subset U of the 2-dimensional topological manifold M sage: s.display() f*g: U → ℝ (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
>>> from sage.all import * >>> f.domain(), g.domain() (2-dimensional topological manifold M, Open subset U of the 2-dimensional topological manifold M) >>> s = f*g ; s Scalar field f*g on the Open subset U of the 2-dimensional topological manifold M >>> s.display() f*g: U → ℝ (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) >>> 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 topological manifold M sage: s.display() f/c: M → ℝ 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 topological manifold M sage: s.display() g/h: U → ℝ (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 f/g on the Open subset U of the 2-dimensional topological manifold M sage: s.display() f/g: U → ℝ (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
>>> from sage.all import * >>> s = f/c ; s Scalar field f/c on the 2-dimensional topological manifold M >>> s.display() f/c: M → ℝ 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) >>> s = g/h ; s Scalar field g/h on the Open subset U of the 2-dimensional topological manifold M >>> s.display() g/h: U → ℝ (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))) >>> s = f/g ; s Scalar field f/g on the Open subset U of the 2-dimensional topological manifold M >>> s.display() f/g: U → ℝ (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) >>> 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 topological manifold M sage: s.display() U → ℝ (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)
>>> from sage.all import * >>> s = g + x**Integer(2) - y ; s Scalar field on the Open subset U of the 2-dimensional topological manifold M >>> s.display() U → ℝ (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 topological manifold M sage: s.display() U → ℝ (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)
>>> from sage.all import * >>> s = g*x ; s Scalar field on the Open subset U of the 2-dimensional topological manifold M >>> s.display() U → ℝ (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 topological manifold M sage: s.display() U → ℝ (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 topological manifold M sage: s.display() U → ℝ (x, y) ↦ 1/y on W: (u, v) ↦ (u^2 + v^2)/v
>>> from sage.all import * >>> s = g/x ; s Scalar field on the Open subset U of the 2-dimensional topological manifold M >>> s.display() U → ℝ (x, y) ↦ y on W: (u, v) ↦ v/(u^2 + v^2) >>> s = x/g ; s Scalar field on the Open subset U of the 2-dimensional topological manifold M >>> s.display() U → ℝ (x, y) ↦ 1/y on W: (u, v) ↦ (u^2 + v^2)/v
Examples with SymPy as the symbolic engine
From now on, we ask that all symbolic calculus on manifold \(M\) are performed by SymPy:
sage: M.set_calculus_method('sympy')
>>> from sage.all import * >>> M.set_calculus_method('sympy')
We define \(f\) as above:
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 topological manifold M sage: f.display() # notice the SymPy display of exponents f: M → ℝ on U: (x, y) ↦ 1/(x**2 + y**2 + 1) on V: (u, v) ↦ (u**2 + v**2)/(u**2 + v**2 + 1) sage: type(f.coord_function(c_xy).expr()) <class 'sympy.core.power.Pow'>
>>> from sage.all import * >>> f = M.scalar_field({c_xy: Integer(1)/(Integer(1)+x**Integer(2)+y**Integer(2)), c_uv: (u**Integer(2)+v**Integer(2))/(Integer(1)+u**Integer(2)+v**Integer(2))}, ... name='f') ; f Scalar field f on the 2-dimensional topological manifold M >>> f.display() # notice the SymPy display of exponents f: M → ℝ on U: (x, y) ↦ 1/(x**2 + y**2 + 1) on V: (u, v) ↦ (u**2 + v**2)/(u**2 + v**2 + 1) >>> type(f.coord_function(c_xy).expr()) <class 'sympy.core.power.Pow'>
The scalar field \(g\) defined on \(U\):
sage: g = U.scalar_field({c_xy: x*y}, name='g') sage: g.display() # again notice the SymPy display of exponents g: U → ℝ (x, y) ↦ x*y on W: (u, v) ↦ u*v/(u**4 + 2*u**2*v**2 + v**4)
>>> from sage.all import * >>> g = U.scalar_field({c_xy: x*y}, name='g') >>> g.display() # again notice the SymPy display of exponents g: U → ℝ (x, y) ↦ x*y on W: (u, v) ↦ u*v/(u**4 + 2*u**2*v**2 + v**4)
Definition on a single chart and subsequent completion:
sage: f = M.scalar_field(1/(1+x^2+y^2), chart=c_xy, name='f') sage: f.add_expr((u^2+v^2)/(1+u^2+v^2), chart=c_uv) sage: f.display() f: M → ℝ on U: (x, y) ↦ 1/(x**2 + y**2 + 1) on V: (u, v) ↦ (u**2 + v**2)/(u**2 + v**2 + 1)
>>> from sage.all import * >>> f = M.scalar_field(Integer(1)/(Integer(1)+x**Integer(2)+y**Integer(2)), chart=c_xy, name='f') >>> f.add_expr((u**Integer(2)+v**Integer(2))/(Integer(1)+u**Integer(2)+v**Integer(2)), chart=c_uv) >>> f.display() f: M → ℝ on U: (x, y) ↦ 1/(x**2 + y**2 + 1) on V: (u, v) ↦ (u**2 + v**2)/(u**2 + v**2 + 1)
Definition without any coordinate expression and subsequent completion:
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 → ℝ on U: (x, y) ↦ 1/(x**2 + y**2 + 1) on V: (u, v) ↦ (u**2 + v**2)/(u**2 + v**2 + 1)
>>> from sage.all import * >>> f = M.scalar_field(name='f') >>> f.add_expr(Integer(1)/(Integer(1)+x**Integer(2)+y**Integer(2)), chart=c_xy) >>> f.add_expr((u**Integer(2)+v**Integer(2))/(Integer(1)+u**Integer(2)+v**Integer(2)), chart=c_uv) >>> f.display() f: M → ℝ on U: (x, y) ↦ 1/(x**2 + y**2 + 1) on V: (u, v) ↦ (u**2 + v**2)/(u**2 + v**2 + 1)
Use of
add_expr_by_continuation()
:sage: f = M.scalar_field(1/(1+x^2+y^2), chart=c_xy, name='f') sage: f.add_expr_by_continuation(c_uv, U.intersection(V)) sage: f.display() f: M → ℝ on U: (x, y) ↦ 1/(x**2 + y**2 + 1) on V: (u, v) ↦ (u**2 + v**2)/(u**2 + v**2 + 1)
>>> from sage.all import * >>> f = M.scalar_field(Integer(1)/(Integer(1)+x**Integer(2)+y**Integer(2)), chart=c_xy, name='f') >>> f.add_expr_by_continuation(c_uv, U.intersection(V)) >>> f.display() f: M → ℝ 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 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 topological manifold M sage: h.display() h: U → ℝ (x, y) ↦ H(x, y) on W: (u, v) ↦ H(u/(u**2 + v**2), v/(u**2 + v**2))
>>> from sage.all import * >>> h = U.scalar_field(function('H')(x, y), name='h') ; h Scalar field h on the Open subset U of the 2-dimensional topological manifold M >>> h.display() h: U → ℝ (x, y) ↦ H(x, y) on W: (u, v) ↦ H(u/(u**2 + v**2), v/(u**2 + v**2))
The coordinate expression in a given chart is obtained via the method
expr()
, which in the present context, returns a SymPy object:sage: f.expr(c_uv) (u**2 + v**2)/(u**2 + v**2 + 1) sage: type(f.expr(c_uv)) <class 'sympy.core.mul.Mul'>
>>> from sage.all import * >>> f.expr(c_uv) (u**2 + v**2)/(u**2 + v**2 + 1) >>> type(f.expr(c_uv)) <class 'sympy.core.mul.Mul'>
The method
coord_function()
returns instead a function of the chart coordinates, i.e. an instance ofChartFunction
: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)
>>> from sage.all import * >>> f.coord_function(c_uv) (u**2 + v**2)/(u**2 + v**2 + 1) >>> type(f.coord_function(c_uv)) <class 'sage.manifolds.chart_func.ChartFunctionRing_with_category.element_class'> >>> f.coord_function(c_uv).display() (u, v) ↦ (u**2 + v**2)/(u**2 + v**2 + 1)
The value returned by the method
expr()
is actually the coordinate expression of the chart function:sage: f.expr(c_uv) is f.coord_function(c_uv).expr() True
>>> from sage.all import * >>> f.expr(c_uv) is f.coord_function(c_uv).expr() True
We may ask for the
SR
representation of the coordinate function:sage: f.coord_function(c_uv).expr('SR') (u^2 + v^2)/(u^2 + v^2 + 1)
>>> from sage.all import * >>> f.coord_function(c_uv).expr('SR') (u^2 + v^2)/(u^2 + v^2 + 1)
A constant scalar field with SymPy representation:
sage: c = M.constant_scalar_field(2, name='c') sage: c.display() c: M → ℝ on U: (x, y) ↦ 2 on V: (u, v) ↦ 2 sage: type(c.expr(c_xy)) <class 'sympy.core.numbers.Integer'>
>>> from sage.all import * >>> c = M.constant_scalar_field(Integer(2), name='c') >>> c.display() c: M → ℝ on U: (x, y) ↦ 2 on V: (u, v) ↦ 2 >>> type(c.expr(c_xy)) <class 'sympy.core.numbers.Integer'>
The constant value can be some unspecified parameter:
sage: var('a') a sage: c = M.constant_scalar_field(a, name='c') sage: c.display() c: M → ℝ on U: (x, y) ↦ a on V: (u, v) ↦ a sage: type(c.expr(c_xy)) <class 'sympy.core.symbol.Symbol'>
>>> from sage.all import * >>> var('a') a >>> c = M.constant_scalar_field(a, name='c') >>> c.display() c: M → ℝ on U: (x, y) ↦ a on V: (u, v) ↦ a >>> type(c.expr(c_xy)) <class 'sympy.core.symbol.Symbol'>
The zero scalar field:
sage: zer = M.constant_scalar_field(0) ; zer Scalar field zero on the 2-dimensional topological manifold M sage: zer.display() zero: M → ℝ on U: (x, y) ↦ 0 on V: (u, v) ↦ 0 sage: type(zer.expr(c_xy)) <class 'sympy.core.numbers.Zero'> sage: zer is M.zero_scalar_field() True
>>> from sage.all import * >>> zer = M.constant_scalar_field(Integer(0)) ; zer Scalar field zero on the 2-dimensional topological manifold M >>> zer.display() zero: M → ℝ on U: (x, y) ↦ 0 on V: (u, v) ↦ 0 >>> type(zer.expr(c_xy)) <class 'sympy.core.numbers.Zero'> >>> zer is M.zero_scalar_field() True
Action of scalar fields on manifold’s points:
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
>>> from sage.all import * >>> N = M.point((Integer(0),Integer(0)), chart=c_uv) # the North pole >>> S = M.point((Integer(0),Integer(0)), chart=c_xy) # the South pole >>> E = M.point((Integer(1),Integer(0)), chart=c_xy) # a point at the equator >>> f(N) 0 >>> f(S) 1 >>> f(E) 1/2 >>> h(E) H(1, 0) >>> c(E) a >>> zer(E) 0
A scalar field can be compared to another scalar field:
sage: f == g False
>>> from sage.all import * >>> f == g False
…to a symbolic expression:
sage: f == x*y False sage: g == x*y True sage: c == a True
>>> from sage.all import * >>> f == x*y False >>> g == x*y True >>> c == a True
…to a number:
sage: f == 2 False sage: zer == 0 True
>>> from sage.all import * >>> f == Integer(2) False >>> zer == Integer(0) True
…to anything else:
sage: f == M False
>>> from sage.all import * >>> f == M False
Standard mathematical functions are implemented:
sage: sqrt(f) Scalar field sqrt(f) on the 2-dimensional topological manifold M sage: sqrt(f).display() sqrt(f): M → ℝ 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)
>>> from sage.all import * >>> sqrt(f) Scalar field sqrt(f) on the 2-dimensional topological manifold M >>> sqrt(f).display() sqrt(f): M → ℝ 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 topological manifold M sage: tan(f).display() tan(f): M → ℝ on U: (x, y) ↦ tan(1/(x**2 + y**2 + 1)) on V: (u, v) ↦ tan((u**2 + v**2)/(u**2 + v**2 + 1))
>>> from sage.all import * >>> tan(f) Scalar field tan(f) on the 2-dimensional topological manifold M >>> tan(f).display() tan(f): M → ℝ on U: (x, y) ↦ tan(1/(x**2 + y**2 + 1)) on V: (u, v) ↦ tan((u**2 + v**2)/(u**2 + v**2 + 1))
Arithmetics of scalar fields with SymPy
Scalar fields on \(M\) (resp. \(U\)) belong to the algebra \(C^0(M)\) (resp. \(C^0(U)\)):
sage: f.parent() Algebra of scalar fields on the 2-dimensional topological manifold M sage: f.parent() is M.scalar_field_algebra() True sage: g.parent() Algebra of scalar fields on the Open subset U of the 2-dimensional topological manifold M sage: g.parent() is U.scalar_field_algebra() True
>>> from sage.all import * >>> f.parent() Algebra of scalar fields on the 2-dimensional topological manifold M >>> f.parent() is M.scalar_field_algebra() True >>> g.parent() Algebra of scalar fields on the Open subset U of the 2-dimensional topological manifold M >>> 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 topological manifold M sage: s.display() f+c: M → ℝ on U: (x, y) ↦ (a*x**2 + a*y**2 + a + 1)/(x**2 + y**2 + 1) on V: (u, v) ↦ (a*u**2 + a*v**2 + a + u**2 + v**2)/(u**2 + v**2 + 1)
>>> from sage.all import * >>> s = f + c ; s Scalar field f+c on the 2-dimensional topological manifold M >>> s.display() f+c: M → ℝ on U: (x, y) ↦ (a*x**2 + a*y**2 + a + 1)/(x**2 + y**2 + 1) on V: (u, v) ↦ (a*u**2 + a*v**2 + a + u**2 + v**2)/(u**2 + v**2 + 1)
and subtracted:
sage: s = f - c ; s Scalar field f-c on the 2-dimensional topological manifold M sage: s.display() f-c: M → ℝ on U: (x, y) ↦ (-a*x**2 - a*y**2 - a + 1)/(x**2 + y**2 + 1) on V: (u, v) ↦ (-a*u**2 - a*v**2 - a + u**2 + v**2)/(u**2 + v**2 + 1)
>>> from sage.all import * >>> s = f - c ; s Scalar field f-c on the 2-dimensional topological manifold M >>> s.display() f-c: M → ℝ on U: (x, y) ↦ (-a*x**2 - a*y**2 - a + 1)/(x**2 + y**2 + 1) on V: (u, v) ↦ (-a*u**2 - a*v**2 - a + u**2 + v**2)/(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
>>> from sage.all import * >>> f + zer == f True >>> f - f == zer True >>> f + (-f) == zer True >>> (f+c)-f == c True >>> (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 f+1 on the 2-dimensional topological manifold M sage: s.display() f+1: M → ℝ 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
>>> from sage.all import * >>> s = f + Integer(1) ; s Scalar field f+1 on the 2-dimensional topological manifold M >>> s.display() f+1: M → ℝ 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) >>> (f+Integer(1))-Integer(1) == f True
The number can represented by a symbolic variable:
sage: s = a + f ; s Scalar field on the 2-dimensional topological manifold M sage: s == c + f True
>>> from sage.all import * >>> s = a + f ; s Scalar field on the 2-dimensional topological manifold M >>> 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 topological manifold M sage: s.display() M → ℝ on U: (x, y) ↦ (x**3 + x*y**2 + x + 1)/(x**2 + y**2 + 1) on W: (u, v) ↦ (u**4 + u**3 + 2*u**2*v**2 + u*v**2 + u + v**4)/(u**4 + 2*u**2*v**2 + u**2 + v**4 + v**2) sage: s = f + u; s Scalar field on the 2-dimensional topological manifold M sage: s.display() M → ℝ on W: (x, y) ↦ (x**3 + x**2 + x*y**2 + x + y**2)/(x**4 + 2*x**2*y**2 + x**2 + y**4 + y**2) on V: (u, v) ↦ (u**3 + u**2 + u*v**2 + u + v**2)/(u**2 + v**2 + 1)
>>> from sage.all import * >>> s = f + x; s Scalar field on the 2-dimensional topological manifold M >>> s.display() M → ℝ on U: (x, y) ↦ (x**3 + x*y**2 + x + 1)/(x**2 + y**2 + 1) on W: (u, v) ↦ (u**4 + u**3 + 2*u**2*v**2 + u*v**2 + u + v**4)/(u**4 + 2*u**2*v**2 + u**2 + v**4 + v**2) >>> s = f + u; s Scalar field on the 2-dimensional topological manifold M >>> s.display() M → ℝ on W: (x, y) ↦ (x**3 + x**2 + x*y**2 + x + y**2)/(x**4 + 2*x**2*y**2 + x**2 + y**4 + y**2) on V: (u, v) ↦ (u**3 + u**2 + u*v**2 + u + v**2)/(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 topological manifold M sage: g.domain() Open subset U of the 2-dimensional topological manifold M sage: s = f + g ; s Scalar field f+g on the Open subset U of the 2-dimensional topological manifold M sage: s.domain() Open subset U of the 2-dimensional topological manifold M sage: s.display() f+g: U → ℝ (x, y) ↦ (x**3*y + x*y**3 + x*y + 1)/(x**2 + y**2 + 1) on W: (u, v) ↦ (u**6 + 3*u**4*v**2 + u**3*v + 3*u**2*v**4 + u*v**3 + u*v + v**6)/(u**6 + 3*u**4*v**2 + u**4 + 3*u**2*v**4 + 2*u**2*v**2 + v**6 + v**4)
>>> from sage.all import * >>> f.domain() 2-dimensional topological manifold M >>> g.domain() Open subset U of the 2-dimensional topological manifold M >>> s = f + g ; s Scalar field f+g on the Open subset U of the 2-dimensional topological manifold M >>> s.domain() Open subset U of the 2-dimensional topological manifold M >>> s.display() f+g: U → ℝ (x, y) ↦ (x**3*y + x*y**3 + x*y + 1)/(x**2 + y**2 + 1) on W: (u, v) ↦ (u**6 + 3*u**4*v**2 + u**3*v + 3*u**2*v**4 + u*v**3 + u*v + v**6)/(u**6 + 3*u**4*v**2 + u**4 + 3*u**2*v**4 + 2*u**2*v**2 + v**6 + v**4)
The operation actually performed is \(f|_U + g\):
sage: s == f.restrict(U) + g True
>>> from sage.all import * >>> s == f.restrict(U) + g True
Since the algebra \(C^0(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 topological manifold M sage: s.display() M → ℝ on U: (x, y) ↦ 2/(x**2 + y**2 + 1) on V: (u, v) ↦ 2*(u**2 + v**2)/(u**2 + v**2 + 1)
>>> from sage.all import * >>> s = Integer(2)*f ; s Scalar field on the 2-dimensional topological manifold M >>> s.display() M → ℝ 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 topological manifold M sage: s.display() M → ℝ on U: (x, y) ↦ a/(x**2 + y**2 + 1) on V: (u, v) ↦ a*(u**2 + v**2)/(u**2 + v**2 + 1)
>>> from sage.all import * >>> s = a*f ; s Scalar field on the 2-dimensional topological manifold M >>> s.display() M → ℝ on U: (x, y) ↦ a/(x**2 + y**2 + 1) on V: (u, v) ↦ a*(u**2 + v**2)/(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 topological manifold M sage: s.display() M → ℝ on U: (x, y) ↦ x/(x**2 + y**2 + 1) on W: (u, v) ↦ u/(u**2 + v**2 + 1) sage: s = u*f; s Scalar field on the 2-dimensional topological manifold M sage: s.display() M → ℝ on W: (x, y) ↦ x/(x**4 + 2*x**2*y**2 + x**2 + y**4 + y**2) on V: (u, v) ↦ u*(u**2 + v**2)/(u**2 + v**2 + 1)
>>> from sage.all import * >>> s = x*f; s Scalar field on the 2-dimensional topological manifold M >>> s.display() M → ℝ on U: (x, y) ↦ x/(x**2 + y**2 + 1) on W: (u, v) ↦ u/(u**2 + v**2 + 1) >>> s = u*f; s Scalar field on the 2-dimensional topological manifold M >>> s.display() M → ℝ on W: (x, y) ↦ x/(x**4 + 2*x**2*y**2 + x**2 + y**4 + y**2) on V: (u, v) ↦ u*(u**2 + v**2)/(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
>>> from sage.all import * >>> Integer(0)*f == Integer(0) True >>> Integer(0)*f == zer True >>> Integer(1)*f == f True >>> (-Integer(2))*f == - f - f True
The ring multiplication of the algebras \(C^0(M)\) and \(C^0(U)\) is the pointwise multiplication of functions:
sage: s = f*f ; s Scalar field f*f on the 2-dimensional topological manifold M sage: s.display() f*f: M → ℝ on U: (x, y) ↦ 1/(x**4 + 2*x**2*y**2 + 2*x**2 + y**4 + 2*y**2 + 1) on V: (u, v) ↦ (u**4 + 2*u**2*v**2 + v**4)/(u**4 + 2*u**2*v**2 + 2*u**2 + v**4 + 2*v**2 + 1) sage: s = g*h ; s Scalar field g*h on the Open subset U of the 2-dimensional topological manifold M sage: s.display() g*h: U → ℝ (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)
>>> from sage.all import * >>> s = f*f ; s Scalar field f*f on the 2-dimensional topological manifold M >>> s.display() f*f: M → ℝ on U: (x, y) ↦ 1/(x**4 + 2*x**2*y**2 + 2*x**2 + y**4 + 2*y**2 + 1) on V: (u, v) ↦ (u**4 + 2*u**2*v**2 + v**4)/(u**4 + 2*u**2*v**2 + 2*u**2 + v**4 + 2*v**2 + 1) >>> s = g*h ; s Scalar field g*h on the Open subset U of the 2-dimensional topological manifold M >>> s.display() g*h: U → ℝ (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^0(M) \to C^0(U)\) mentioned 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 topological manifold M, Open subset U of the 2-dimensional topological manifold M) sage: s = f*g ; s Scalar field f*g on the Open subset U of the 2-dimensional topological manifold M sage: s.display() f*g: U → ℝ (x, y) ↦ x*y/(x**2 + y**2 + 1) on W: (u, v) ↦ u*v/(u**4 + 2*u**2*v**2 + u**2 + v**4 + v**2) sage: s == f.restrict(U)*g True
>>> from sage.all import * >>> f.domain(), g.domain() (2-dimensional topological manifold M, Open subset U of the 2-dimensional topological manifold M) >>> s = f*g ; s Scalar field f*g on the Open subset U of the 2-dimensional topological manifold M >>> s.display() f*g: U → ℝ (x, y) ↦ x*y/(x**2 + y**2 + 1) on W: (u, v) ↦ u*v/(u**4 + 2*u**2*v**2 + u**2 + v**4 + v**2) >>> 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 topological manifold M sage: s.display() f/c: M → ℝ on U: (x, y) ↦ 1/(a*(x**2 + y**2 + 1)) on V: (u, v) ↦ (u**2 + v**2)/(a*(u**2 + v**2 + 1)) sage: s = g/h ; s Scalar field g/h on the Open subset U of the 2-dimensional topological manifold M sage: s.display() g/h: U → ℝ (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 f/g on the Open subset U of the 2-dimensional topological manifold M sage: s.display() f/g: U → ℝ (x, y) ↦ 1/(x*y*(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*(u**2 + v**2 + 1)) sage: s == f.restrict(U)/g True
>>> from sage.all import * >>> s = f/c ; s Scalar field f/c on the 2-dimensional topological manifold M >>> s.display() f/c: M → ℝ on U: (x, y) ↦ 1/(a*(x**2 + y**2 + 1)) on V: (u, v) ↦ (u**2 + v**2)/(a*(u**2 + v**2 + 1)) >>> s = g/h ; s Scalar field g/h on the Open subset U of the 2-dimensional topological manifold M >>> s.display() g/h: U → ℝ (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))) >>> s = f/g ; s Scalar field f/g on the Open subset U of the 2-dimensional topological manifold M >>> s.display() f/g: U → ℝ (x, y) ↦ 1/(x*y*(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*(u**2 + v**2 + 1)) >>> 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 topological manifold M sage: s.display() U → ℝ (x, y) ↦ x**2 + x*y - y on W: (u, v) ↦ (-u**2*v + u**2 + u*v - v**3)/(u**4 + 2*u**2*v**2 + v**4)
>>> from sage.all import * >>> s = g + x**Integer(2) - y ; s Scalar field on the Open subset U of the 2-dimensional topological manifold M >>> s.display() U → ℝ (x, y) ↦ x**2 + x*y - y on W: (u, v) ↦ (-u**2*v + u**2 + u*v - v**3)/(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 topological manifold M sage: s.display() U → ℝ (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)
>>> from sage.all import * >>> s = g*x ; s Scalar field on the Open subset U of the 2-dimensional topological manifold M >>> s.display() U → ℝ (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 topological manifold M sage: s.display() U → ℝ (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 topological manifold M sage: s.display() U → ℝ (x, y) ↦ 1/y on W: (u, v) ↦ u**2/v + v
>>> from sage.all import * >>> s = g/x ; s Scalar field on the Open subset U of the 2-dimensional topological manifold M >>> s.display() U → ℝ (x, y) ↦ y on W: (u, v) ↦ v/(u**2 + v**2) >>> s = x/g ; s Scalar field on the Open subset U of the 2-dimensional topological manifold M >>> s.display() U → ℝ (x, y) ↦ 1/y on W: (u, v) ↦ u**2/v + v
The test suite is passed:
sage: TestSuite(f).run() sage: TestSuite(zer).run()
>>> from sage.all import * >>> TestSuite(f).run() >>> TestSuite(zer).run()
- add_expr(coord_expression, chart=None)[source]#
Add some coordinate expression to the scalar field.
The previous expressions with respect to other charts are kept. To clear them, use
set_expr()
instead.INPUT:
coord_expression
– coordinate expression of the scalar fieldchart
– (default:None
) chart in whichcoord_expression
is defined; ifNone
, the default chart of the scalar field’s domain is assumed
Warning
If the scalar field has already expressions in other charts, it is the user’s responsibility to make sure that the expression to be added is consistent with them.
EXAMPLES:
Adding scalar field expressions on a 2-dimensional manifold:
sage: M = Manifold(2, 'M', structure='topological') sage: c_xy.<x,y> = M.chart() sage: f = M.scalar_field(x^2 + 2*x*y +1) sage: f._express {Chart (M, (x, y)): x^2 + 2*x*y + 1} sage: f.add_expr(3*y) sage: f._express # the (x,y) expression has been changed: {Chart (M, (x, y)): 3*y} sage: c_uv.<u,v> = M.chart() sage: f.add_expr(cos(u)-sin(v), c_uv) sage: f._express # random (dict. output); f has now 2 expressions: {Chart (M, (x, y)): 3*y, Chart (M, (u, v)): cos(u) - sin(v)}
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> c_xy = M.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2) >>> f = M.scalar_field(x**Integer(2) + Integer(2)*x*y +Integer(1)) >>> f._express {Chart (M, (x, y)): x^2 + 2*x*y + 1} >>> f.add_expr(Integer(3)*y) >>> f._express # the (x,y) expression has been changed: {Chart (M, (x, y)): 3*y} >>> c_uv = M.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2) >>> f.add_expr(cos(u)-sin(v), c_uv) >>> f._express # random (dict. output); f has now 2 expressions: {Chart (M, (x, y)): 3*y, Chart (M, (u, v)): cos(u) - sin(v)}
Since zero and one are special elements, their expressions cannot be changed:
sage: z = M.zero_scalar_field() sage: z.add_expr(cos(u)-sin(v), c_uv) Traceback (most recent call last): ... ValueError: the expressions of an immutable element cannot be changed sage: one = M.one_scalar_field() sage: one.add_expr(cos(u)-sin(v), c_uv) Traceback (most recent call last): ... ValueError: the expressions of an immutable element cannot be changed
>>> from sage.all import * >>> z = M.zero_scalar_field() >>> z.add_expr(cos(u)-sin(v), c_uv) Traceback (most recent call last): ... ValueError: the expressions of an immutable element cannot be changed >>> one = M.one_scalar_field() >>> one.add_expr(cos(u)-sin(v), c_uv) Traceback (most recent call last): ... ValueError: the expressions of an immutable element cannot be changed
- add_expr_by_continuation(chart, subdomain)[source]#
Set coordinate expression in a chart by continuation of the coordinate expression in a subchart.
The continuation is performed by demanding that the coordinate expression is identical to that in the restriction of the chart to a given subdomain.
INPUT:
chart
– coordinate chart \((U,(x^i))\) in which the expression of the scalar field is to setsubdomain
– open subset \(V\subset U\) in which the expression in terms of the restriction of the coordinate chart \((U,(x^i))\) to \(V\) is already known or can be evaluated by a change of coordinates.
EXAMPLES:
Scalar field on the sphere \(S^2\):
sage: M = Manifold(2, 'S^2', structure='topological') sage: U = M.open_subset('U') ; V = M.open_subset('V') # the complement of resp. N pole and S pole sage: M.declare_union(U,V) # S^2 is the union of U and V sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart() # stereographic coordinates 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: W = U.intersection(V) # S^2 minus the two poles sage: f = M.scalar_field(atan(x^2+y^2), chart=c_xy, name='f')
>>> from sage.all import * >>> M = Manifold(Integer(2), 'S^2', structure='topological') >>> U = M.open_subset('U') ; V = M.open_subset('V') # the complement of resp. N pole and S pole >>> M.declare_union(U,V) # S^2 is the union of U and V >>> c_xy = U.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2); c_uv = V.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2)# stereographic coordinates >>> xy_to_uv = c_xy.transition_map(c_uv, (x/(x**Integer(2)+y**Integer(2)), y/(x**Integer(2)+y**Integer(2))), ... intersection_name='W', restrictions1= x**Integer(2)+y**Integer(2)!=Integer(0), ... restrictions2= u**Integer(2)+v**Integer(2)!=Integer(0)) >>> uv_to_xy = xy_to_uv.inverse() >>> W = U.intersection(V) # S^2 minus the two poles >>> f = M.scalar_field(atan(x**Integer(2)+y**Integer(2)), chart=c_xy, name='f')
The scalar field has been defined only on the domain covered by the chart
c_xy
, i.e. \(U\):sage: f.display() f: S^2 → ℝ on U: (x, y) ↦ arctan(x^2 + y^2) on W: (u, v) ↦ arctan(1/(u^2 + v^2))
>>> from sage.all import * >>> f.display() f: S^2 → ℝ on U: (x, y) ↦ arctan(x^2 + y^2) on W: (u, v) ↦ arctan(1/(u^2 + v^2))
We note that on \(W = U \cap V\), the expression of \(f\) in terms of coordinates \((u,v)\) can be deduced from that in the coordinates \((x,y)\) thanks to the transition map between the two charts:
sage: f.display(c_uv.restrict(W)) f: S^2 → ℝ on W: (u, v) ↦ arctan(1/(u^2 + v^2))
>>> from sage.all import * >>> f.display(c_uv.restrict(W)) f: S^2 → ℝ on W: (u, v) ↦ arctan(1/(u^2 + v^2))
We use this fact to extend the definition of \(f\) to the open subset \(V\), covered by the chart
c_uv
:sage: f.add_expr_by_continuation(c_uv, W)
>>> from sage.all import * >>> f.add_expr_by_continuation(c_uv, W)
Then, \(f\) is known on the whole sphere:
sage: f.display() f: S^2 → ℝ on U: (x, y) ↦ arctan(x^2 + y^2) on V: (u, v) ↦ arctan(1/(u^2 + v^2))
>>> from sage.all import * >>> f.display() f: S^2 → ℝ on U: (x, y) ↦ arctan(x^2 + y^2) on V: (u, v) ↦ arctan(1/(u^2 + v^2))
- arccos()[source]#
Arc cosine of the scalar field.
OUTPUT:
the scalar field \(\arccos f\), where \(f\) is the current scalar field
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") sage: g = arccos(f) ; g Scalar field arccos(f) on the 2-dimensional topological manifold M sage: latex(g) \arccos\left(\Phi\right) sage: g.display() arccos(f): M → ℝ (x, y) ↦ arccos(x*y)
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") >>> g = arccos(f) ; g Scalar field arccos(f) on the 2-dimensional topological manifold M >>> latex(g) \arccos\left(\Phi\right) >>> g.display() arccos(f): M → ℝ (x, y) ↦ arccos(x*y)
The notation
acos
can be used as well:sage: acos(f) Scalar field arccos(f) on the 2-dimensional topological manifold M sage: acos(f) == g True
>>> from sage.all import * >>> acos(f) Scalar field arccos(f) on the 2-dimensional topological manifold M >>> acos(f) == g True
Some tests:
sage: cos(g) == f True sage: arccos(M.constant_scalar_field(1)) == M.zero_scalar_field() True sage: arccos(M.zero_scalar_field()) == M.constant_scalar_field(pi/2) True
>>> from sage.all import * >>> cos(g) == f True >>> arccos(M.constant_scalar_field(Integer(1))) == M.zero_scalar_field() True >>> arccos(M.zero_scalar_field()) == M.constant_scalar_field(pi/Integer(2)) True
- arccosh()[source]#
Inverse hyperbolic cosine of the scalar field.
OUTPUT:
the scalar field \(\mathrm{arccosh}\, f\), where \(f\) is the current scalar field
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") sage: g = arccosh(f) ; g Scalar field arccosh(f) on the 2-dimensional topological manifold M sage: latex(g) \,\mathrm{arccosh}\left(\Phi\right) sage: g.display() arccosh(f): M → ℝ (x, y) ↦ arccosh(x*y)
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") >>> g = arccosh(f) ; g Scalar field arccosh(f) on the 2-dimensional topological manifold M >>> latex(g) \,\mathrm{arccosh}\left(\Phi\right) >>> g.display() arccosh(f): M → ℝ (x, y) ↦ arccosh(x*y)
The notation
acosh
can be used as well:sage: acosh(f) Scalar field arccosh(f) on the 2-dimensional topological manifold M sage: acosh(f) == g True
>>> from sage.all import * >>> acosh(f) Scalar field arccosh(f) on the 2-dimensional topological manifold M >>> acosh(f) == g True
Some tests:
sage: cosh(g) == f True sage: arccosh(M.constant_scalar_field(1)) == M.zero_scalar_field() True
>>> from sage.all import * >>> cosh(g) == f True >>> arccosh(M.constant_scalar_field(Integer(1))) == M.zero_scalar_field() True
- arcsin()[source]#
Arc sine of the scalar field.
OUTPUT:
the scalar field \(\arcsin f\), where \(f\) is the current scalar field
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") sage: g = arcsin(f) ; g Scalar field arcsin(f) on the 2-dimensional topological manifold M sage: latex(g) \arcsin\left(\Phi\right) sage: g.display() arcsin(f): M → ℝ (x, y) ↦ arcsin(x*y)
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") >>> g = arcsin(f) ; g Scalar field arcsin(f) on the 2-dimensional topological manifold M >>> latex(g) \arcsin\left(\Phi\right) >>> g.display() arcsin(f): M → ℝ (x, y) ↦ arcsin(x*y)
The notation
asin
can be used as well:sage: asin(f) Scalar field arcsin(f) on the 2-dimensional topological manifold M sage: asin(f) == g True
>>> from sage.all import * >>> asin(f) Scalar field arcsin(f) on the 2-dimensional topological manifold M >>> asin(f) == g True
Some tests:
sage: sin(g) == f True sage: arcsin(M.zero_scalar_field()) == M.zero_scalar_field() True sage: arcsin(M.constant_scalar_field(1)) == M.constant_scalar_field(pi/2) True
>>> from sage.all import * >>> sin(g) == f True >>> arcsin(M.zero_scalar_field()) == M.zero_scalar_field() True >>> arcsin(M.constant_scalar_field(Integer(1))) == M.constant_scalar_field(pi/Integer(2)) True
- arcsinh()[source]#
Inverse hyperbolic sine of the scalar field.
OUTPUT:
the scalar field \(\mathrm{arcsinh}\, f\), where \(f\) is the current scalar field
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") sage: g = arcsinh(f) ; g Scalar field arcsinh(f) on the 2-dimensional topological manifold M sage: latex(g) \,\mathrm{arcsinh}\left(\Phi\right) sage: g.display() arcsinh(f): M → ℝ (x, y) ↦ arcsinh(x*y)
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") >>> g = arcsinh(f) ; g Scalar field arcsinh(f) on the 2-dimensional topological manifold M >>> latex(g) \,\mathrm{arcsinh}\left(\Phi\right) >>> g.display() arcsinh(f): M → ℝ (x, y) ↦ arcsinh(x*y)
The notation
asinh
can be used as well:sage: asinh(f) Scalar field arcsinh(f) on the 2-dimensional topological manifold M sage: asinh(f) == g True
>>> from sage.all import * >>> asinh(f) Scalar field arcsinh(f) on the 2-dimensional topological manifold M >>> asinh(f) == g True
Some tests:
sage: sinh(g) == f True sage: arcsinh(M.zero_scalar_field()) == M.zero_scalar_field() True
>>> from sage.all import * >>> sinh(g) == f True >>> arcsinh(M.zero_scalar_field()) == M.zero_scalar_field() True
- arctan()[source]#
Arc tangent of the scalar field.
OUTPUT:
the scalar field \(\arctan f\), where \(f\) is the current scalar field
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") sage: g = arctan(f) ; g Scalar field arctan(f) on the 2-dimensional topological manifold M sage: latex(g) \arctan\left(\Phi\right) sage: g.display() arctan(f): M → ℝ (x, y) ↦ arctan(x*y)
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") >>> g = arctan(f) ; g Scalar field arctan(f) on the 2-dimensional topological manifold M >>> latex(g) \arctan\left(\Phi\right) >>> g.display() arctan(f): M → ℝ (x, y) ↦ arctan(x*y)
The notation
atan
can be used as well:sage: atan(f) Scalar field arctan(f) on the 2-dimensional topological manifold M sage: atan(f) == g True
>>> from sage.all import * >>> atan(f) Scalar field arctan(f) on the 2-dimensional topological manifold M >>> atan(f) == g True
Some tests:
sage: tan(g) == f True sage: arctan(M.zero_scalar_field()) == M.zero_scalar_field() True sage: arctan(M.constant_scalar_field(1)) == M.constant_scalar_field(pi/4) True
>>> from sage.all import * >>> tan(g) == f True >>> arctan(M.zero_scalar_field()) == M.zero_scalar_field() True >>> arctan(M.constant_scalar_field(Integer(1))) == M.constant_scalar_field(pi/Integer(4)) True
- arctanh()[source]#
Inverse hyperbolic tangent of the scalar field.
OUTPUT:
the scalar field \(\mathrm{arctanh}\, f\), where \(f\) is the current scalar field
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") sage: g = arctanh(f) ; g Scalar field arctanh(f) on the 2-dimensional topological manifold M sage: latex(g) \,\mathrm{arctanh}\left(\Phi\right) sage: g.display() arctanh(f): M → ℝ (x, y) ↦ arctanh(x*y)
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") >>> g = arctanh(f) ; g Scalar field arctanh(f) on the 2-dimensional topological manifold M >>> latex(g) \,\mathrm{arctanh}\left(\Phi\right) >>> g.display() arctanh(f): M → ℝ (x, y) ↦ arctanh(x*y)
The notation
atanh
can be used as well:sage: atanh(f) Scalar field arctanh(f) on the 2-dimensional topological manifold M sage: atanh(f) == g True
>>> from sage.all import * >>> atanh(f) Scalar field arctanh(f) on the 2-dimensional topological manifold M >>> atanh(f) == g True
Some tests:
sage: tanh(g) == f True sage: arctanh(M.zero_scalar_field()) == M.zero_scalar_field() True sage: arctanh(M.constant_scalar_field(1/2)) == M.constant_scalar_field(log(3)/2) True
>>> from sage.all import * >>> tanh(g) == f True >>> arctanh(M.zero_scalar_field()) == M.zero_scalar_field() True >>> arctanh(M.constant_scalar_field(Integer(1)/Integer(2))) == M.constant_scalar_field(log(Integer(3))/Integer(2)) True
- codomain()[source]#
Return the codomain of the scalar field.
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: c_xy.<x,y> = M.chart() sage: f = M.scalar_field(x+2*y) sage: f.codomain() Real Field with 53 bits of precision
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> c_xy = M.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2) >>> f = M.scalar_field(x+Integer(2)*y) >>> f.codomain() Real Field with 53 bits of precision
- common_charts(other)[source]#
Find common charts for the expressions of the scalar field and
other
.INPUT:
other
– a scalar field
OUTPUT:
list of common charts; if no common chart is found,
None
is returned (instead of an empty list)
EXAMPLES:
Search for common charts on a 2-dimensional manifold with 2 overlapping domains:
sage: M = Manifold(2, 'M', structure='topological') sage: U = M.open_subset('U') sage: c_xy.<x,y> = U.chart() sage: V = M.open_subset('V') sage: c_uv.<u,v> = V.chart() sage: M.declare_union(U,V) # M is the union of U and V sage: f = U.scalar_field(x^2) sage: g = M.scalar_field(x+y) sage: f.common_charts(g) [Chart (U, (x, y))] sage: g.add_expr(u, c_uv) sage: f._express {Chart (U, (x, y)): x^2} sage: g._express # random (dictionary output) {Chart (U, (x, y)): x + y, Chart (V, (u, v)): u} sage: f.common_charts(g) [Chart (U, (x, y))]
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> U = M.open_subset('U') >>> c_xy = U.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2) >>> V = M.open_subset('V') >>> c_uv = V.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2) >>> M.declare_union(U,V) # M is the union of U and V >>> f = U.scalar_field(x**Integer(2)) >>> g = M.scalar_field(x+y) >>> f.common_charts(g) [Chart (U, (x, y))] >>> g.add_expr(u, c_uv) >>> f._express {Chart (U, (x, y)): x^2} >>> g._express # random (dictionary output) {Chart (U, (x, y)): x + y, Chart (V, (u, v)): u} >>> f.common_charts(g) [Chart (U, (x, y))]
Common charts found as subcharts: the subcharts are introduced via a transition map between charts c_xy and c_uv on the intersecting subdomain \(W = U\cap V\):
sage: trans = c_xy.transition_map(c_uv, (x+y, x-y), 'W', x<0, u+v<0) sage: M.atlas() [Chart (U, (x, y)), Chart (V, (u, v)), Chart (W, (x, y)), Chart (W, (u, v))] sage: c_xy_W = M.atlas()[2] sage: c_uv_W = M.atlas()[3] sage: trans.inverse() Change of coordinates from Chart (W, (u, v)) to Chart (W, (x, y)) sage: f.common_charts(g) [Chart (U, (x, y))] sage: f.expr(c_xy_W) x^2 sage: f._express # random (dictionary output) {Chart (U, (x, y)): x^2, Chart (W, (x, y)): x^2} sage: g._express # random (dictionary output) {Chart (U, (x, y)): x + y, Chart (V, (u, v)): u} sage: g.common_charts(f) # c_xy_W is not returned because it is subchart of 'xy' [Chart (U, (x, y))] sage: f.expr(c_uv_W) 1/4*u^2 + 1/2*u*v + 1/4*v^2 sage: f._express # random (dictionary output) {Chart (U, (x, y)): x^2, Chart (W, (x, y)): x^2, Chart (W, (u, v)): 1/4*u^2 + 1/2*u*v + 1/4*v^2} sage: g._express # random (dictionary output) {Chart (U, (x, y)): x + y, Chart (V, (u, v)): u} sage: f.common_charts(g) [Chart (U, (x, y)), Chart (W, (u, v))] sage: # the expressions have been updated on the subcharts sage: g._express # random (dictionary output) {Chart (U, (x, y)): x + y, Chart (V, (u, v)): u, Chart (W, (u, v)): u}
>>> from sage.all import * >>> trans = c_xy.transition_map(c_uv, (x+y, x-y), 'W', x<Integer(0), u+v<Integer(0)) >>> M.atlas() [Chart (U, (x, y)), Chart (V, (u, v)), Chart (W, (x, y)), Chart (W, (u, v))] >>> c_xy_W = M.atlas()[Integer(2)] >>> c_uv_W = M.atlas()[Integer(3)] >>> trans.inverse() Change of coordinates from Chart (W, (u, v)) to Chart (W, (x, y)) >>> f.common_charts(g) [Chart (U, (x, y))] >>> f.expr(c_xy_W) x^2 >>> f._express # random (dictionary output) {Chart (U, (x, y)): x^2, Chart (W, (x, y)): x^2} >>> g._express # random (dictionary output) {Chart (U, (x, y)): x + y, Chart (V, (u, v)): u} >>> g.common_charts(f) # c_xy_W is not returned because it is subchart of 'xy' [Chart (U, (x, y))] >>> f.expr(c_uv_W) 1/4*u^2 + 1/2*u*v + 1/4*v^2 >>> f._express # random (dictionary output) {Chart (U, (x, y)): x^2, Chart (W, (x, y)): x^2, Chart (W, (u, v)): 1/4*u^2 + 1/2*u*v + 1/4*v^2} >>> g._express # random (dictionary output) {Chart (U, (x, y)): x + y, Chart (V, (u, v)): u} >>> f.common_charts(g) [Chart (U, (x, y)), Chart (W, (u, v))] >>> # the expressions have been updated on the subcharts >>> g._express # random (dictionary output) {Chart (U, (x, y)): x + y, Chart (V, (u, v)): u, Chart (W, (u, v)): u}
Common charts found by computing some coordinate changes:
sage: W = U.intersection(V) sage: f = W.scalar_field(x^2, c_xy_W) sage: g = W.scalar_field(u+1, c_uv_W) sage: f._express {Chart (W, (x, y)): x^2} sage: g._express {Chart (W, (u, v)): u + 1} sage: f.common_charts(g) [Chart (W, (x, y)), Chart (W, (u, v))] sage: f._express # random (dictionary output) {Chart (W, (u, v)): 1/4*u^2 + 1/2*u*v + 1/4*v^2, Chart (W, (x, y)): x^2} sage: g._express # random (dictionary output) {Chart (W, (u, v)): u + 1, Chart (W, (x, y)): x + y + 1}
>>> from sage.all import * >>> W = U.intersection(V) >>> f = W.scalar_field(x**Integer(2), c_xy_W) >>> g = W.scalar_field(u+Integer(1), c_uv_W) >>> f._express {Chart (W, (x, y)): x^2} >>> g._express {Chart (W, (u, v)): u + 1} >>> f.common_charts(g) [Chart (W, (x, y)), Chart (W, (u, v))] >>> f._express # random (dictionary output) {Chart (W, (u, v)): 1/4*u^2 + 1/2*u*v + 1/4*v^2, Chart (W, (x, y)): x^2} >>> g._express # random (dictionary output) {Chart (W, (u, v)): u + 1, Chart (W, (x, y)): x + y + 1}
- coord_function(chart=None, from_chart=None)[source]#
Return the function of the coordinates representing the scalar field in a given chart.
INPUT:
chart
– (default:None
) chart with respect to which the coordinate expression is to be returned; ifNone
, the default chart of the scalar field’s domain will be usedfrom_chart
– (default:None
) chart from which the required expression is computed if it is not known already in the chartchart
; ifNone
, a chart is picked in the known expressions
OUTPUT:
instance of
ChartFunction
representing the coordinate function of the scalar field in the given chart
EXAMPLES:
Coordinate function on a 2-dimensional manifold:
sage: M = Manifold(2, 'M', structure='topological') sage: c_xy.<x,y> = M.chart() sage: f = M.scalar_field(x*y^2) sage: f.coord_function() x*y^2 sage: f.coord_function(c_xy) # equivalent form (since c_xy is the default chart) x*y^2 sage: type(f.coord_function()) <class 'sage.manifolds.chart_func.ChartFunctionRing_with_category.element_class'>
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> c_xy = M.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2) >>> f = M.scalar_field(x*y**Integer(2)) >>> f.coord_function() x*y^2 >>> f.coord_function(c_xy) # equivalent form (since c_xy is the default chart) x*y^2 >>> type(f.coord_function()) <class 'sage.manifolds.chart_func.ChartFunctionRing_with_category.element_class'>
Expression via a change of coordinates:
sage: c_uv.<u,v> = M.chart() sage: c_uv.transition_map(c_xy, [u+v, u-v]) Change of coordinates from Chart (M, (u, v)) to Chart (M, (x, y)) sage: f._express # at this stage, f is expressed only in terms of (x,y) coordinates {Chart (M, (x, y)): x*y^2} sage: f.coord_function(c_uv) # forces the computation of the expression of f in terms of (u,v) coordinates u^3 - u^2*v - u*v^2 + v^3 sage: f.coord_function(c_uv) == (u+v)*(u-v)^2 # check True sage: f._express # random (dict. output); f has now 2 coordinate expressions: {Chart (M, (x, y)): x*y^2, Chart (M, (u, v)): u^3 - u^2*v - u*v^2 + v^3}
>>> from sage.all import * >>> c_uv = M.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2) >>> c_uv.transition_map(c_xy, [u+v, u-v]) Change of coordinates from Chart (M, (u, v)) to Chart (M, (x, y)) >>> f._express # at this stage, f is expressed only in terms of (x,y) coordinates {Chart (M, (x, y)): x*y^2} >>> f.coord_function(c_uv) # forces the computation of the expression of f in terms of (u,v) coordinates u^3 - u^2*v - u*v^2 + v^3 >>> f.coord_function(c_uv) == (u+v)*(u-v)**Integer(2) # check True >>> f._express # random (dict. output); f has now 2 coordinate expressions: {Chart (M, (x, y)): x*y^2, Chart (M, (u, v)): u^3 - u^2*v - u*v^2 + v^3}
Usage in a physical context (simple Lorentz transformation - boost in
x
direction, with relative velocityv
betweeno1
ando2
frames):sage: M = Manifold(2, 'M', structure='topological') sage: o1.<t,x> = M.chart() sage: o2.<T,X> = M.chart() sage: f = M.scalar_field(x^2 - t^2) sage: f.coord_function(o1) -t^2 + x^2 sage: v = var('v'); gam = 1/sqrt(1-v^2) sage: o2.transition_map(o1, [gam*(T - v*X), gam*(X - v*T)]) Change of coordinates from Chart (M, (T, X)) to Chart (M, (t, x)) sage: f.coord_function(o2) -T^2 + X^2
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> o1 = M.chart(names=('t', 'x',)); (t, x,) = o1._first_ngens(2) >>> o2 = M.chart(names=('T', 'X',)); (T, X,) = o2._first_ngens(2) >>> f = M.scalar_field(x**Integer(2) - t**Integer(2)) >>> f.coord_function(o1) -t^2 + x^2 >>> v = var('v'); gam = Integer(1)/sqrt(Integer(1)-v**Integer(2)) >>> o2.transition_map(o1, [gam*(T - v*X), gam*(X - v*T)]) Change of coordinates from Chart (M, (T, X)) to Chart (M, (t, x)) >>> f.coord_function(o2) -T^2 + X^2
- copy(name=None, latex_name=None)[source]#
Return an exact copy of the scalar field.
INPUT:
name
– (default:None
) name given to the copylatex_name
– (default:None
) LaTeX symbol to denote the copy; if none is provided, the LaTeX symbol is set toname
EXAMPLES:
Copy on a 2-dimensional manifold:
sage: M = Manifold(2, 'M', structure='topological') sage: c_xy.<x,y> = M.chart() sage: f = M.scalar_field(x*y^2) sage: g = f.copy() sage: type(g) <class 'sage.manifolds.scalarfield_algebra.ScalarFieldAlgebra_with_category.element_class'> sage: g.expr() x*y^2 sage: g == f True sage: g is f False
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> c_xy = M.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2) >>> f = M.scalar_field(x*y**Integer(2)) >>> g = f.copy() >>> type(g) <class 'sage.manifolds.scalarfield_algebra.ScalarFieldAlgebra_with_category.element_class'> >>> g.expr() x*y^2 >>> g == f True >>> g is f False
- copy_from(other)[source]#
Make
self
a copy ofother
.INPUT:
other
– other scalar field, in the same module asself
Note
While the derived quantities are not copied, the name is kept.
Warning
All previous defined expressions and restrictions will be deleted!
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: c_xy.<x,y> = M.chart() sage: f = M.scalar_field(x*y^2, name='f') sage: f.display() f: M → ℝ (x, y) ↦ x*y^2 sage: g = M.scalar_field(name='g') sage: g.copy_from(f) sage: g.display() g: M → ℝ (x, y) ↦ x*y^2 sage: f == g True
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> c_xy = M.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2) >>> f = M.scalar_field(x*y**Integer(2), name='f') >>> f.display() f: M → ℝ (x, y) ↦ x*y^2 >>> g = M.scalar_field(name='g') >>> g.copy_from(f) >>> g.display() g: M → ℝ (x, y) ↦ x*y^2 >>> f == g True
While the original scalar field is modified, the copy is not:
sage: f.set_expr(x-y) sage: f.display() f: M → ℝ (x, y) ↦ x - y sage: g.display() g: M → ℝ (x, y) ↦ x*y^2 sage: f == g False
>>> from sage.all import * >>> f.set_expr(x-y) >>> f.display() f: M → ℝ (x, y) ↦ x - y >>> g.display() g: M → ℝ (x, y) ↦ x*y^2 >>> f == g False
- cos()[source]#
Cosine of the scalar field.
OUTPUT:
the scalar field \(\cos f\), where \(f\) is the current scalar field
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") sage: g = cos(f) ; g Scalar field cos(f) on the 2-dimensional topological manifold M sage: latex(g) \cos\left(\Phi\right) sage: g.display() cos(f): M → ℝ (x, y) ↦ cos(x*y)
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") >>> g = cos(f) ; g Scalar field cos(f) on the 2-dimensional topological manifold M >>> latex(g) \cos\left(\Phi\right) >>> g.display() cos(f): M → ℝ (x, y) ↦ cos(x*y)
Some tests:
sage: cos(M.zero_scalar_field()) == M.constant_scalar_field(1) True sage: cos(M.constant_scalar_field(pi/2)) == M.zero_scalar_field() True
>>> from sage.all import * >>> cos(M.zero_scalar_field()) == M.constant_scalar_field(Integer(1)) True >>> cos(M.constant_scalar_field(pi/Integer(2))) == M.zero_scalar_field() True
- cosh()[source]#
Hyperbolic cosine of the scalar field.
OUTPUT:
the scalar field \(\cosh f\), where \(f\) is the current scalar field
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") sage: g = cosh(f) ; g Scalar field cosh(f) on the 2-dimensional topological manifold M sage: latex(g) \cosh\left(\Phi\right) sage: g.display() cosh(f): M → ℝ (x, y) ↦ cosh(x*y)
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") >>> g = cosh(f) ; g Scalar field cosh(f) on the 2-dimensional topological manifold M >>> latex(g) \cosh\left(\Phi\right) >>> g.display() cosh(f): M → ℝ (x, y) ↦ cosh(x*y)
Some test:
sage: cosh(M.zero_scalar_field()) == M.constant_scalar_field(1) True
>>> from sage.all import * >>> cosh(M.zero_scalar_field()) == M.constant_scalar_field(Integer(1)) True
- disp(chart=None)[source]#
Display the expression of the scalar field in a given chart.
Without any argument, this function displays all known, distinct expressions.
INPUT:
chart
– (default:None
) chart with respect to which the coordinate expression is to be displayed; ifNone
, the display is performed in all the greatest charts in which the coordinate expression is known
The output is either text-formatted (console mode) or LaTeX-formatted (notebook mode).
EXAMPLES:
Various displays:
sage: M = Manifold(2, 'M', structure='topological') sage: c_xy.<x,y> = M.chart() sage: f = M.scalar_field(sqrt(x+1), name='f') sage: f.display() f: M → ℝ (x, y) ↦ sqrt(x + 1) sage: latex(f.display()) \begin{array}{llcl} f:& M & \longrightarrow & \mathbb{R} \\ & \left(x, y\right) & \longmapsto & \sqrt{x + 1} \end{array} sage: g = M.scalar_field(function('G')(x, y), name='g') sage: g.display() g: M → ℝ (x, y) ↦ G(x, y) sage: latex(g.display()) \begin{array}{llcl} g:& M & \longrightarrow & \mathbb{R} \\ & \left(x, y\right) & \longmapsto & G\left(x, y\right) \end{array}
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> c_xy = M.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2) >>> f = M.scalar_field(sqrt(x+Integer(1)), name='f') >>> f.display() f: M → ℝ (x, y) ↦ sqrt(x + 1) >>> latex(f.display()) \begin{array}{llcl} f:& M & \longrightarrow & \mathbb{R} \\ & \left(x, y\right) & \longmapsto & \sqrt{x + 1} \end{array} >>> g = M.scalar_field(function('G')(x, y), name='g') >>> g.display() g: M → ℝ (x, y) ↦ G(x, y) >>> latex(g.display()) \begin{array}{llcl} g:& M & \longrightarrow & \mathbb{R} \\ & \left(x, y\right) & \longmapsto & G\left(x, y\right) \end{array}
A shortcut of
display()
isdisp()
:sage: f.disp() f: M → ℝ (x, y) ↦ sqrt(x + 1)
>>> from sage.all import * >>> f.disp() f: M → ℝ (x, y) ↦ sqrt(x + 1)
In case the scalar field is piecewise-defined, the
display()
command still outputs all expressions. Each expression displayed corresponds to the chart on the greatest domain where this particular expression is known:sage: U = M.open_subset('U') sage: f.set_expr(y^2, c_xy.restrict(U)) sage: f.display() f: M → ℝ on U: (x, y) ↦ y^2 sage: latex(f.display()) \begin{array}{llcl} f:& M & \longrightarrow & \mathbb{R} \\ \text{on}\ U : & \left(x, y\right) & \longmapsto & y^{2} \end{array}
>>> from sage.all import * >>> U = M.open_subset('U') >>> f.set_expr(y**Integer(2), c_xy.restrict(U)) >>> f.display() f: M → ℝ on U: (x, y) ↦ y^2 >>> latex(f.display()) \begin{array}{llcl} f:& M & \longrightarrow & \mathbb{R} \\ \text{on}\ U : & \left(x, y\right) & \longmapsto & y^{2} \end{array}
- display(chart=None)[source]#
Display the expression of the scalar field in a given chart.
Without any argument, this function displays all known, distinct expressions.
INPUT:
chart
– (default:None
) chart with respect to which the coordinate expression is to be displayed; ifNone
, the display is performed in all the greatest charts in which the coordinate expression is known
The output is either text-formatted (console mode) or LaTeX-formatted (notebook mode).
EXAMPLES:
Various displays:
sage: M = Manifold(2, 'M', structure='topological') sage: c_xy.<x,y> = M.chart() sage: f = M.scalar_field(sqrt(x+1), name='f') sage: f.display() f: M → ℝ (x, y) ↦ sqrt(x + 1) sage: latex(f.display()) \begin{array}{llcl} f:& M & \longrightarrow & \mathbb{R} \\ & \left(x, y\right) & \longmapsto & \sqrt{x + 1} \end{array} sage: g = M.scalar_field(function('G')(x, y), name='g') sage: g.display() g: M → ℝ (x, y) ↦ G(x, y) sage: latex(g.display()) \begin{array}{llcl} g:& M & \longrightarrow & \mathbb{R} \\ & \left(x, y\right) & \longmapsto & G\left(x, y\right) \end{array}
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> c_xy = M.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2) >>> f = M.scalar_field(sqrt(x+Integer(1)), name='f') >>> f.display() f: M → ℝ (x, y) ↦ sqrt(x + 1) >>> latex(f.display()) \begin{array}{llcl} f:& M & \longrightarrow & \mathbb{R} \\ & \left(x, y\right) & \longmapsto & \sqrt{x + 1} \end{array} >>> g = M.scalar_field(function('G')(x, y), name='g') >>> g.display() g: M → ℝ (x, y) ↦ G(x, y) >>> latex(g.display()) \begin{array}{llcl} g:& M & \longrightarrow & \mathbb{R} \\ & \left(x, y\right) & \longmapsto & G\left(x, y\right) \end{array}
A shortcut of
display()
isdisp()
:sage: f.disp() f: M → ℝ (x, y) ↦ sqrt(x + 1)
>>> from sage.all import * >>> f.disp() f: M → ℝ (x, y) ↦ sqrt(x + 1)
In case the scalar field is piecewise-defined, the
display()
command still outputs all expressions. Each expression displayed corresponds to the chart on the greatest domain where this particular expression is known:sage: U = M.open_subset('U') sage: f.set_expr(y^2, c_xy.restrict(U)) sage: f.display() f: M → ℝ on U: (x, y) ↦ y^2 sage: latex(f.display()) \begin{array}{llcl} f:& M & \longrightarrow & \mathbb{R} \\ \text{on}\ U : & \left(x, y\right) & \longmapsto & y^{2} \end{array}
>>> from sage.all import * >>> U = M.open_subset('U') >>> f.set_expr(y**Integer(2), c_xy.restrict(U)) >>> f.display() f: M → ℝ on U: (x, y) ↦ y^2 >>> latex(f.display()) \begin{array}{llcl} f:& M & \longrightarrow & \mathbb{R} \\ \text{on}\ U : & \left(x, y\right) & \longmapsto & y^{2} \end{array}
- domain()[source]#
Return the open subset on which the scalar field is defined.
OUTPUT:
instance of class
TopologicalManifold
representing the manifold’s open subset on which the scalar field is defined
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: c_xy.<x,y> = M.chart() sage: f = M.scalar_field(x+2*y) sage: f.domain() 2-dimensional topological manifold M sage: U = M.open_subset('U', coord_def={c_xy: x<0}) sage: g = f.restrict(U) sage: g.domain() Open subset U of the 2-dimensional topological manifold M
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> c_xy = M.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2) >>> f = M.scalar_field(x+Integer(2)*y) >>> f.domain() 2-dimensional topological manifold M >>> U = M.open_subset('U', coord_def={c_xy: x<Integer(0)}) >>> g = f.restrict(U) >>> g.domain() Open subset U of the 2-dimensional topological manifold M
- exp()[source]#
Exponential of the scalar field.
OUTPUT:
the scalar field \(\exp f\), where \(f\) is the current scalar field
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x+y}, name='f', latex_name=r"\Phi") sage: g = exp(f) ; g Scalar field exp(f) on the 2-dimensional topological manifold M sage: g.display() exp(f): M → ℝ (x, y) ↦ e^(x + y) sage: latex(g) \exp\left(\Phi\right)
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: x+y}, name='f', latex_name=r"\Phi") >>> g = exp(f) ; g Scalar field exp(f) on the 2-dimensional topological manifold M >>> g.display() exp(f): M → ℝ (x, y) ↦ e^(x + y) >>> latex(g) \exp\left(\Phi\right)
Automatic simplifications occur:
sage: f = M.scalar_field({X: 2*ln(1+x^2)}, name='f') sage: exp(f).display() exp(f): M → ℝ (x, y) ↦ x^4 + 2*x^2 + 1
>>> from sage.all import * >>> f = M.scalar_field({X: Integer(2)*ln(Integer(1)+x**Integer(2))}, name='f') >>> exp(f).display() exp(f): M → ℝ (x, y) ↦ x^4 + 2*x^2 + 1
The inverse function is
log()
:sage: log(exp(f)) == f True
>>> from sage.all import * >>> log(exp(f)) == f True
Some tests:
sage: exp(M.zero_scalar_field()) == M.constant_scalar_field(1) True sage: exp(M.constant_scalar_field(1)) == M.constant_scalar_field(e) True
>>> from sage.all import * >>> exp(M.zero_scalar_field()) == M.constant_scalar_field(Integer(1)) True >>> exp(M.constant_scalar_field(Integer(1))) == M.constant_scalar_field(e) True
- expr(chart=None, from_chart=None)[source]#
Return the coordinate expression of the scalar field in a given chart.
INPUT:
chart
– (default:None
) chart with respect to which the coordinate expression is required; ifNone
, the default chart of the scalar field’s domain will be usedfrom_chart
– (default:None
) chart from which the required expression is computed if it is not known already in the chartchart
; ifNone
, a chart is picked inself._express
OUTPUT:
the coordinate expression of the scalar field in the given chart, either as a Sage’s symbolic expression or as a SymPy object, depending on the symbolic calculus method used on the chart
EXAMPLES:
Expression of a scalar field on a 2-dimensional manifold:
sage: M = Manifold(2, 'M', structure='topological') sage: c_xy.<x,y> = M.chart() sage: f = M.scalar_field(x*y^2) sage: f.expr() x*y^2 sage: f.expr(c_xy) # equivalent form (since c_xy is the default chart) x*y^2
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> c_xy = M.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2) >>> f = M.scalar_field(x*y**Integer(2)) >>> f.expr() x*y^2 >>> f.expr(c_xy) # equivalent form (since c_xy is the default chart) x*y^2
Expression via a change of coordinates:
sage: c_uv.<u,v> = M.chart() sage: c_uv.transition_map(c_xy, [u+v, u-v]) Change of coordinates from Chart (M, (u, v)) to Chart (M, (x, y)) sage: f._express # at this stage, f is expressed only in terms of (x,y) coordinates {Chart (M, (x, y)): x*y^2} sage: f.expr(c_uv) # forces the computation of the expression of f in terms of (u,v) coordinates u^3 - u^2*v - u*v^2 + v^3 sage: bool( f.expr(c_uv) == (u+v)*(u-v)^2 ) # check True sage: f._express # random (dict. output); f has now 2 coordinate expressions: {Chart (M, (x, y)): x*y^2, Chart (M, (u, v)): u^3 - u^2*v - u*v^2 + v^3}
>>> from sage.all import * >>> c_uv = M.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2) >>> c_uv.transition_map(c_xy, [u+v, u-v]) Change of coordinates from Chart (M, (u, v)) to Chart (M, (x, y)) >>> f._express # at this stage, f is expressed only in terms of (x,y) coordinates {Chart (M, (x, y)): x*y^2} >>> f.expr(c_uv) # forces the computation of the expression of f in terms of (u,v) coordinates u^3 - u^2*v - u*v^2 + v^3 >>> bool( f.expr(c_uv) == (u+v)*(u-v)**Integer(2) ) # check True >>> f._express # random (dict. output); f has now 2 coordinate expressions: {Chart (M, (x, y)): x*y^2, Chart (M, (u, v)): u^3 - u^2*v - u*v^2 + v^3}
Note that the object returned by
expr()
depends on the symbolic backend used for coordinate computations:sage: type(f.expr()) <class 'sage.symbolic.expression.Expression'> sage: M.set_calculus_method('sympy') sage: type(f.expr()) <class 'sympy.core.mul.Mul'> sage: f.expr() # note the SymPy exponent notation x*y**2
>>> from sage.all import * >>> type(f.expr()) <class 'sage.symbolic.expression.Expression'> >>> M.set_calculus_method('sympy') >>> type(f.expr()) <class 'sympy.core.mul.Mul'> >>> f.expr() # note the SymPy exponent notation x*y**2
- is_trivial_one()[source]#
Check if
self
is trivially equal to one without any simplification.This method is supposed to be fast as compared with
self == 1
and is intended to be used in library code where trying to obtain a mathematically correct result by applying potentially expensive rewrite rules is not desirable.EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: 1}) sage: f.is_trivial_one() True sage: f = M.scalar_field(1) sage: f.is_trivial_one() True sage: M.one_scalar_field().is_trivial_one() True sage: f = M.scalar_field({X: x+y}) sage: f.is_trivial_one() False
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: Integer(1)}) >>> f.is_trivial_one() True >>> f = M.scalar_field(Integer(1)) >>> f.is_trivial_one() True >>> M.one_scalar_field().is_trivial_one() True >>> f = M.scalar_field({X: x+y}) >>> f.is_trivial_one() False
Scalar field defined by means of two charts:
sage: U1 = M.open_subset('U1'); X1.<x1,y1> = U1.chart() sage: U2 = M.open_subset('U2'); X2.<x2,y2> = U2.chart() sage: f = M.scalar_field({X1: 1, X2: 1}) sage: f.is_trivial_one() True sage: f = M.scalar_field({X1: 0, X2: 1}) sage: f.is_trivial_one() False
>>> from sage.all import * >>> U1 = M.open_subset('U1'); X1 = U1.chart(names=('x1', 'y1',)); (x1, y1,) = X1._first_ngens(2) >>> U2 = M.open_subset('U2'); X2 = U2.chart(names=('x2', 'y2',)); (x2, y2,) = X2._first_ngens(2) >>> f = M.scalar_field({X1: Integer(1), X2: Integer(1)}) >>> f.is_trivial_one() True >>> f = M.scalar_field({X1: Integer(0), X2: Integer(1)}) >>> f.is_trivial_one() False
No simplification is attempted, so that
False
is returned for non-trivial cases:sage: f = M.scalar_field({X: cos(x)^2 + sin(x)^2}) sage: f.is_trivial_one() False
>>> from sage.all import * >>> f = M.scalar_field({X: cos(x)**Integer(2) + sin(x)**Integer(2)}) >>> f.is_trivial_one() False
On the contrary, the method
is_zero()
and the direct comparison to one involve some simplification algorithms and returnTrue
:sage: (f - 1).is_zero() True sage: f == 1 True
>>> from sage.all import * >>> (f - Integer(1)).is_zero() True >>> f == Integer(1) True
- is_trivial_zero()[source]#
Check if
self
is trivially equal to zero without any simplification.This method is supposed to be fast as compared with
self.is_zero()
orself == 0
and is intended to be used in library code where trying to obtain a mathematically correct result by applying potentially expensive rewrite rules is not desirable.EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: 0}) sage: f.is_trivial_zero() True sage: f = M.scalar_field(0) sage: f.is_trivial_zero() True sage: M.zero_scalar_field().is_trivial_zero() True sage: f = M.scalar_field({X: x+y}) sage: f.is_trivial_zero() False
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: Integer(0)}) >>> f.is_trivial_zero() True >>> f = M.scalar_field(Integer(0)) >>> f.is_trivial_zero() True >>> M.zero_scalar_field().is_trivial_zero() True >>> f = M.scalar_field({X: x+y}) >>> f.is_trivial_zero() False
Scalar field defined by means of two charts:
sage: U1 = M.open_subset('U1'); X1.<x1,y1> = U1.chart() sage: U2 = M.open_subset('U2'); X2.<x2,y2> = U2.chart() sage: f = M.scalar_field({X1: 0, X2: 0}) sage: f.is_trivial_zero() True sage: f = M.scalar_field({X1: 0, X2: 1}) sage: f.is_trivial_zero() False
>>> from sage.all import * >>> U1 = M.open_subset('U1'); X1 = U1.chart(names=('x1', 'y1',)); (x1, y1,) = X1._first_ngens(2) >>> U2 = M.open_subset('U2'); X2 = U2.chart(names=('x2', 'y2',)); (x2, y2,) = X2._first_ngens(2) >>> f = M.scalar_field({X1: Integer(0), X2: Integer(0)}) >>> f.is_trivial_zero() True >>> f = M.scalar_field({X1: Integer(0), X2: Integer(1)}) >>> f.is_trivial_zero() False
No simplification is attempted, so that
False
is returned for non-trivial cases:sage: f = M.scalar_field({X: cos(x)^2 + sin(x)^2 - 1}) sage: f.is_trivial_zero() False
>>> from sage.all import * >>> f = M.scalar_field({X: cos(x)**Integer(2) + sin(x)**Integer(2) - Integer(1)}) >>> f.is_trivial_zero() False
On the contrary, the method
is_zero()
and the direct comparison to zero involve some simplification algorithms and returnTrue
:sage: f.is_zero() True sage: f == 0 True
>>> from sage.all import * >>> f.is_zero() True >>> f == Integer(0) True
- is_unit()[source]#
Return
True
iffself
is not trivially zero in at least one of the given expressions since most scalar fields are invertible and a complete computation would take too much time.EXAMPLES:
sage: M = Manifold(2, 'M', structure='top') sage: one = M.scalar_field_algebra().one() sage: one.is_unit() True sage: zero = M.scalar_field_algebra().zero() sage: zero.is_unit() False
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='top') >>> one = M.scalar_field_algebra().one() >>> one.is_unit() True >>> zero = M.scalar_field_algebra().zero() >>> zero.is_unit() False
- log()[source]#
Natural logarithm of the scalar field.
OUTPUT:
the scalar field \(\ln f\), where \(f\) is the current scalar field
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x+y}, name='f', latex_name=r"\Phi") sage: g = log(f) ; g Scalar field ln(f) on the 2-dimensional topological manifold M sage: g.display() ln(f): M → ℝ (x, y) ↦ log(x + y) sage: latex(g) \ln\left(\Phi\right)
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: x+y}, name='f', latex_name=r"\Phi") >>> g = log(f) ; g Scalar field ln(f) on the 2-dimensional topological manifold M >>> g.display() ln(f): M → ℝ (x, y) ↦ log(x + y) >>> latex(g) \ln\left(\Phi\right)
The inverse function is
exp()
:sage: exp(log(f)) == f True
>>> from sage.all import * >>> exp(log(f)) == f True
- preimage(codomain_subset, name=None, latex_name=None)[source]#
Return the preimage of
codomain_subset
.An alias is
pullback()
.INPUT:
codomain_subset
– an instance ofRealSet
name
– string; name (symbol) given to the subsetlatex_name
– (default:None
) string; LaTeX symbol to denote the subset; if none are provided, it is set toname
OUTPUT:
either a
TopologicalManifold
or aManifoldSubsetPullback
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x+y}, name='f') sage: L = f.pullback(RealSet.point(1)); latex(L) f^{-1}(\{1\}) sage: M((-1, 1)) in L False sage: M((0, 1)) in L True sage: M.zero_scalar_field().preimage(RealSet.point(0)) is M True
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: x+y}, name='f') >>> L = f.pullback(RealSet.point(Integer(1))); latex(L) f^{-1}(\{1\}) >>> M((-Integer(1), Integer(1))) in L False >>> M((Integer(0), Integer(1))) in L True >>> M.zero_scalar_field().preimage(RealSet.point(Integer(0))) is M True
- pullback(codomain_subset, name=None, latex_name=None)[source]#
Return the preimage of
codomain_subset
.An alias is
pullback()
.INPUT:
codomain_subset
– an instance ofRealSet
name
– string; name (symbol) given to the subsetlatex_name
– (default:None
) string; LaTeX symbol to denote the subset; if none are provided, it is set toname
OUTPUT:
either a
TopologicalManifold
or aManifoldSubsetPullback
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x+y}, name='f') sage: L = f.pullback(RealSet.point(1)); latex(L) f^{-1}(\{1\}) sage: M((-1, 1)) in L False sage: M((0, 1)) in L True sage: M.zero_scalar_field().preimage(RealSet.point(0)) is M True
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: x+y}, name='f') >>> L = f.pullback(RealSet.point(Integer(1))); latex(L) f^{-1}(\{1\}) >>> M((-Integer(1), Integer(1))) in L False >>> M((Integer(0), Integer(1))) in L True >>> M.zero_scalar_field().preimage(RealSet.point(Integer(0))) is M True
- restrict(subdomain)[source]#
Restriction of the scalar field to an open subset of its domain of definition.
INPUT:
subdomain
– an open subset of the scalar field’s domain
OUTPUT:
instance of
ScalarField
representing the restriction of the scalar field tosubdomain
EXAMPLES:
Restriction of a scalar field defined on \(\RR^2\) to the unit open disc:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() # Cartesian coordinates sage: U = M.open_subset('U', coord_def={X: x^2+y^2 < 1}) # U unit open disc sage: f = M.scalar_field(cos(x*y), name='f') sage: f_U = f.restrict(U) ; f_U Scalar field f on the Open subset U of the 2-dimensional topological manifold M sage: f_U.display() f: U → ℝ (x, y) ↦ cos(x*y) sage: f.parent() Algebra of scalar fields on the 2-dimensional topological manifold M sage: f_U.parent() Algebra of scalar fields on the Open subset U of the 2-dimensional topological manifold M
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2)# Cartesian coordinates >>> U = M.open_subset('U', coord_def={X: x**Integer(2)+y**Integer(2) < Integer(1)}) # U unit open disc >>> f = M.scalar_field(cos(x*y), name='f') >>> f_U = f.restrict(U) ; f_U Scalar field f on the Open subset U of the 2-dimensional topological manifold M >>> f_U.display() f: U → ℝ (x, y) ↦ cos(x*y) >>> f.parent() Algebra of scalar fields on the 2-dimensional topological manifold M >>> f_U.parent() Algebra of scalar fields on the Open subset U of the 2-dimensional topological manifold M
The restriction to the whole domain is the identity:
sage: f.restrict(M) is f True sage: f_U.restrict(U) is f_U True
>>> from sage.all import * >>> f.restrict(M) is f True >>> f_U.restrict(U) is f_U True
Restriction of the zero scalar field:
sage: M.zero_scalar_field().restrict(U) Scalar field zero on the Open subset U of the 2-dimensional topological manifold M sage: M.zero_scalar_field().restrict(U) is U.zero_scalar_field() True
>>> from sage.all import * >>> M.zero_scalar_field().restrict(U) Scalar field zero on the Open subset U of the 2-dimensional topological manifold M >>> M.zero_scalar_field().restrict(U) is U.zero_scalar_field() True
- set_calc_order(symbol, order, truncate=False)[source]#
Trigger a power series expansion with respect to a small parameter in computations involving the scalar field.
This property is propagated by usual operations. The internal representation must be
SR
for this to take effect.If the small parameter is \(\epsilon\) and \(f\) is
self
, the power series expansion to order \(n\) is\[f = f_0 + \epsilon f_1 + \epsilon^2 f_2 + \cdots + \epsilon^n f_n + O(\epsilon^{n+1}),\]where \(f_0, f_1, \ldots, f_n\) are \(n+1\) scalar fields that do not depend upon \(\epsilon\).
INPUT:
symbol
– symbolic variable (the “small parameter” \(\epsilon\)) with respect to which the coordinate expressions ofself
in various charts are expanded in power series (around the zero value of this variable)order
– integer; the order \(n\) of the expansion, defined as the degree of the polynomial representing the truncated power series insymbol
Warning
The order of the big \(O\) in the power series expansion is \(n+1\), where \(n\) is
order
.truncate
– (default:False
) determines whether the coordinate expressions ofself
are replaced by their expansions to the given order
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: t = var('t') # the small parameter sage: f = M.scalar_field(exp(-t*x)) sage: f.expr() e^(-t*x) sage: f.set_calc_order(t, 2, truncate=True) sage: f.expr() 1/2*t^2*x^2 - t*x + 1
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> t = var('t') # the small parameter >>> f = M.scalar_field(exp(-t*x)) >>> f.expr() e^(-t*x) >>> f.set_calc_order(t, Integer(2), truncate=True) >>> f.expr() 1/2*t^2*x^2 - t*x + 1
- set_expr(coord_expression, chart=None)[source]#
Set the coordinate expression of the scalar field.
The expressions with respect to other charts are deleted, in order to avoid any inconsistency. To keep them, use
add_expr()
instead.INPUT:
coord_expression
– coordinate expression of the scalar fieldchart
– (default:None
) chart in whichcoord_expression
is defined; ifNone
, the default chart of the scalar field’s domain is assumed
EXAMPLES:
Setting scalar field expressions on a 2-dimensional manifold:
sage: M = Manifold(2, 'M', structure='topological') sage: c_xy.<x,y> = M.chart() sage: f = M.scalar_field(x^2 + 2*x*y +1) sage: f._express {Chart (M, (x, y)): x^2 + 2*x*y + 1} sage: f.set_expr(3*y) sage: f._express # the (x,y) expression has been changed: {Chart (M, (x, y)): 3*y} sage: c_uv.<u,v> = M.chart() sage: f.set_expr(cos(u)-sin(v), c_uv) sage: f._express # the (x,y) expression has been lost: {Chart (M, (u, v)): cos(u) - sin(v)} sage: f.set_expr(3*y) sage: f._express # the (u,v) expression has been lost: {Chart (M, (x, y)): 3*y}
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> c_xy = M.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2) >>> f = M.scalar_field(x**Integer(2) + Integer(2)*x*y +Integer(1)) >>> f._express {Chart (M, (x, y)): x^2 + 2*x*y + 1} >>> f.set_expr(Integer(3)*y) >>> f._express # the (x,y) expression has been changed: {Chart (M, (x, y)): 3*y} >>> c_uv = M.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2) >>> f.set_expr(cos(u)-sin(v), c_uv) >>> f._express # the (x,y) expression has been lost: {Chart (M, (u, v)): cos(u) - sin(v)} >>> f.set_expr(Integer(3)*y) >>> f._express # the (u,v) expression has been lost: {Chart (M, (x, y)): 3*y}
Since zero and one are special elements, their expressions cannot be changed:
sage: z = M.zero_scalar_field() sage: z.set_expr(3*y) Traceback (most recent call last): ... ValueError: the expressions of an immutable element cannot be changed sage: one = M.one_scalar_field() sage: one.set_expr(3*y) Traceback (most recent call last): ... ValueError: the expressions of an immutable element cannot be changed
>>> from sage.all import * >>> z = M.zero_scalar_field() >>> z.set_expr(Integer(3)*y) Traceback (most recent call last): ... ValueError: the expressions of an immutable element cannot be changed >>> one = M.one_scalar_field() >>> one.set_expr(Integer(3)*y) Traceback (most recent call last): ... ValueError: the expressions of an immutable element cannot be changed
- set_immutable()[source]#
Set
self
and all restrictions ofself
immutable.EXAMPLES:
sage: M = Manifold(2, 'M') sage: X.<x,y> = M.chart() sage: U = M.open_subset('U', coord_def={X: x^2+y^2<1}) # disk sage: V = M.open_subset('U', coord_def={X: x>0}) # half plane sage: f = M.scalar_field(x^2, name='f') sage: fU = f.restrict(U) sage: f.set_immutable() sage: fU.is_immutable() True sage: f.restrict(V).is_immutable() True
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> U = M.open_subset('U', coord_def={X: x**Integer(2)+y**Integer(2)<Integer(1)}) # disk >>> V = M.open_subset('U', coord_def={X: x>Integer(0)}) # half plane >>> f = M.scalar_field(x**Integer(2), name='f') >>> fU = f.restrict(U) >>> f.set_immutable() >>> fU.is_immutable() True >>> f.restrict(V).is_immutable() True
- set_name(name=None, latex_name=None)[source]#
Set (or change) the text name and LaTeX name of the scalar field.
INPUT:
name
– (string; default:None
) name given to the scalar fieldlatex_name
– (string; default:None
) LaTeX symbol to denote the scalar field; ifNone
whilename
is provided, the LaTeX symbol is set toname
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x+y}) sage: f = M.scalar_field({X: x+y}); f Scalar field on the 2-dimensional topological manifold M sage: f.set_name('f'); f Scalar field f on the 2-dimensional topological manifold M sage: latex(f) f sage: f.set_name('f', latex_name=r'\Phi'); f Scalar field f on the 2-dimensional topological manifold M sage: latex(f) \Phi
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: x+y}) >>> f = M.scalar_field({X: x+y}); f Scalar field on the 2-dimensional topological manifold M >>> f.set_name('f'); f Scalar field f on the 2-dimensional topological manifold M >>> latex(f) f >>> f.set_name('f', latex_name=r'\Phi'); f Scalar field f on the 2-dimensional topological manifold M >>> latex(f) \Phi
- set_restriction(rst)[source]#
Define a restriction of
self
to some subdomain.INPUT:
rst
–ScalarField
defined on a subdomain of the domain ofself
EXAMPLES:
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: f = M.scalar_field(name='f') sage: g = U.scalar_field(x^2+y) sage: f.set_restriction(g) sage: f.display() f: M → ℝ on U: (x, y) ↦ x^2 + y sage: f.restrict(U) == g True
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M') # the 2-dimensional sphere S^2 >>> U = M.open_subset('U') # complement of the North pole >>> c_xy = U.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2)# stereographic coordinates from the North pole >>> V = M.open_subset('V') # complement of the South pole >>> c_uv = V.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2)# stereographic coordinates from the South pole >>> M.declare_union(U,V) # S^2 is the union of U and V >>> f = M.scalar_field(name='f') >>> g = U.scalar_field(x**Integer(2)+y) >>> f.set_restriction(g) >>> f.display() f: M → ℝ on U: (x, y) ↦ x^2 + y >>> f.restrict(U) == g True
- sin()[source]#
Sine of the scalar field.
OUTPUT:
the scalar field \(\sin f\), where \(f\) is the current scalar field
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") sage: g = sin(f) ; g Scalar field sin(f) on the 2-dimensional topological manifold M sage: latex(g) \sin\left(\Phi\right) sage: g.display() sin(f): M → ℝ (x, y) ↦ sin(x*y)
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") >>> g = sin(f) ; g Scalar field sin(f) on the 2-dimensional topological manifold M >>> latex(g) \sin\left(\Phi\right) >>> g.display() sin(f): M → ℝ (x, y) ↦ sin(x*y)
Some tests:
sage: sin(M.zero_scalar_field()) == M.zero_scalar_field() True sage: sin(M.constant_scalar_field(pi/2)) == M.constant_scalar_field(1) True
>>> from sage.all import * >>> sin(M.zero_scalar_field()) == M.zero_scalar_field() True >>> sin(M.constant_scalar_field(pi/Integer(2))) == M.constant_scalar_field(Integer(1)) True
- sinh()[source]#
Hyperbolic sine of the scalar field.
OUTPUT:
the scalar field \(\sinh f\), where \(f\) is the current scalar field
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") sage: g = sinh(f) ; g Scalar field sinh(f) on the 2-dimensional topological manifold M sage: latex(g) \sinh\left(\Phi\right) sage: g.display() sinh(f): M → ℝ (x, y) ↦ sinh(x*y)
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") >>> g = sinh(f) ; g Scalar field sinh(f) on the 2-dimensional topological manifold M >>> latex(g) \sinh\left(\Phi\right) >>> g.display() sinh(f): M → ℝ (x, y) ↦ sinh(x*y)
Some test:
sage: sinh(M.zero_scalar_field()) == M.zero_scalar_field() True
>>> from sage.all import * >>> sinh(M.zero_scalar_field()) == M.zero_scalar_field() True
- sqrt()[source]#
Square root of the scalar field.
OUTPUT:
the scalar field \(\sqrt f\), where \(f\) is the current scalar field
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: 1+x^2+y^2}, name='f', ....: latex_name=r"\Phi") sage: g = sqrt(f) ; g Scalar field sqrt(f) on the 2-dimensional topological manifold M sage: latex(g) \sqrt{\Phi} sage: g.display() sqrt(f): M → ℝ (x, y) ↦ sqrt(x^2 + y^2 + 1)
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: Integer(1)+x**Integer(2)+y**Integer(2)}, name='f', ... latex_name=r"\Phi") >>> g = sqrt(f) ; g Scalar field sqrt(f) on the 2-dimensional topological manifold M >>> latex(g) \sqrt{\Phi} >>> g.display() sqrt(f): M → ℝ (x, y) ↦ sqrt(x^2 + y^2 + 1)
Some tests:
sage: g^2 == f True sage: sqrt(M.zero_scalar_field()) == M.zero_scalar_field() True
>>> from sage.all import * >>> g**Integer(2) == f True >>> sqrt(M.zero_scalar_field()) == M.zero_scalar_field() True
- tan()[source]#
Tangent of the scalar field.
OUTPUT:
the scalar field \(\tan f\), where \(f\) is the current scalar field
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") sage: g = tan(f) ; g Scalar field tan(f) on the 2-dimensional topological manifold M sage: latex(g) \tan\left(\Phi\right) sage: g.display() tan(f): M → ℝ (x, y) ↦ sin(x*y)/cos(x*y)
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") >>> g = tan(f) ; g Scalar field tan(f) on the 2-dimensional topological manifold M >>> latex(g) \tan\left(\Phi\right) >>> g.display() tan(f): M → ℝ (x, y) ↦ sin(x*y)/cos(x*y)
Some tests:
sage: tan(f) == sin(f) / cos(f) True sage: tan(M.zero_scalar_field()) == M.zero_scalar_field() True sage: tan(M.constant_scalar_field(pi/4)) == M.constant_scalar_field(1) True
>>> from sage.all import * >>> tan(f) == sin(f) / cos(f) True >>> tan(M.zero_scalar_field()) == M.zero_scalar_field() True >>> tan(M.constant_scalar_field(pi/Integer(4))) == M.constant_scalar_field(Integer(1)) True
- tanh()[source]#
Hyperbolic tangent of the scalar field.
OUTPUT:
the scalar field \(\tanh f\), where \(f\) is the current scalar field
EXAMPLES:
sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") sage: g = tanh(f) ; g Scalar field tanh(f) on the 2-dimensional topological manifold M sage: latex(g) \tanh\left(\Phi\right) sage: g.display() tanh(f): M → ℝ (x, y) ↦ sinh(x*y)/cosh(x*y)
>>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) >>> f = M.scalar_field({X: x*y}, name='f', latex_name=r"\Phi") >>> g = tanh(f) ; g Scalar field tanh(f) on the 2-dimensional topological manifold M >>> latex(g) \tanh\left(\Phi\right) >>> g.display() tanh(f): M → ℝ (x, y) ↦ sinh(x*y)/cosh(x*y)
Some tests:
sage: tanh(f) == sinh(f) / cosh(f) True sage: tanh(M.zero_scalar_field()) == M.zero_scalar_field() True
>>> from sage.all import * >>> tanh(f) == sinh(f) / cosh(f) True >>> tanh(M.zero_scalar_field()) == M.zero_scalar_field() True