Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" Tensor Field Modules
The set of tensor fields along a differentiable manifold `U` with values on a differentiable manifold `M` via a differentiable map `\Phi: U \rightarrow M` (possibly `U = M` and `\Phi = \mathrm{Id}_M`) is a module over the algebra `C^k(U)` of differentiable scalar fields on `U`. It is a free module if and only if `M` is parallelizable. Accordingly, two classes are devoted to tensor field modules:
- :class:`TensorFieldModule` for tensor fields with values on a generic (in practice, not parallelizable) differentiable manifold `M`, - :class:`TensorFieldFreeModule` for tensor fields with values on a parallelizable manifold `M`.
AUTHORS:
- Eric Gourgoulhon, Michal Bejger (2014-2015): initial version - Travis Scrimshaw (2016): review tweaks
REFERENCES:
- [KN1963]_ - [Lee2013]_ - [ONe1983]_
"""
#****************************************************************************** # Copyright (C) 2015 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr> # Copyright (C) 2015 Michal Bejger <bejger@camk.edu.pl> # Copyright (C) 2016 Travis Scrimshaw <tscrimsh@umn.edu> # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # http://www.gnu.org/licenses/ #******************************************************************************
DiffFormParal) MultivectorFieldParal) AutomorphismFieldParal)
r""" Module of tensor fields of a given type `(k,l)` along a differentiable manifold `U` with values on a differentiable manifold `M`, via a differentiable map `U \rightarrow M`.
Given two non-negative integers `k` and `l` and a differentiable map
.. MATH::
\Phi:\ U \longrightarrow M,
the *tensor field module* `T^{(k,l)}(U,\Phi)` is the set of all tensor fields of the type
.. MATH::
t:\ U \longrightarrow T^{(k,l)} M
(where `T^{(k,l)} M` is the tensor bundle of type `(k,l)` over `M`) such that
.. MATH::
t(p) \in T^{(k,l)}(T_{\Phi(p)}M)
for all `p \in U`, i.e. `t(p)` is a tensor of type `(k,l)` on the tangent vector space `T_{\Phi(p)} M`. The set `T^{(k,l)}(U,\Phi)` is a module over `C^k(U)`, the ring (algebra) of differentiable scalar fields on `U` (see :class:`~sage.manifolds.differentiable.scalarfield_algebra.DiffScalarFieldAlgebra`).
The standard case of tensor fields *on* a differentiable manifold corresponds to `U = M` and `\Phi = \mathrm{Id}_M`; we then denote `T^{(k,l)}(M,\mathrm{Id}_M)` by merely `T^{(k,l)}(M)`. Other common cases are `\Phi` being an immersion and `\Phi` being a curve in `M` (`U` is then an open interval of `\RR`).
.. NOTE::
If `M` is parallelizable, the class :class:`TensorFieldFreeModule` should be used instead.
INPUT:
- ``vector_field_module`` -- module `\mathfrak{X}(U,\Phi)` of vector fields along `U` associated with the map `\Phi: U \rightarrow M` - ``tensor_type`` -- pair `(k,l)` with `k` being the contravariant rank and `l` the covariant rank
EXAMPLES:
Module of type-`(2,0)` tensor fields on the 2-sphere::
sage: M = Manifold(2, 'M') # the 2-dimensional sphere S^2 sage: U = M.open_subset('U') # complement of the North pole sage: c_xy.<x,y> = U.chart() # stereographic coordinates from the North pole sage: V = M.open_subset('V') # complement of the South pole sage: c_uv.<u,v> = V.chart() # stereographic coordinates from the South pole sage: M.declare_union(U,V) # S^2 is the union of U and V sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)), ....: intersection_name='W', restrictions1= x^2+y^2!=0, ....: restrictions2= u^2+v^2!=0) sage: uv_to_xy = xy_to_uv.inverse() sage: W = U.intersection(V) sage: T20 = M.tensor_field_module((2,0)); T20 Module T^(2,0)(M) of type-(2,0) tensors fields on the 2-dimensional differentiable manifold M
`T^{(2,0)}(M)` is a module over the algebra `C^k(M)`::
sage: T20.category() Category of modules over Algebra of differentiable scalar fields on the 2-dimensional differentiable manifold M sage: T20.base_ring() is M.scalar_field_algebra() True
`T^{(2,0)}(M)` is not a free module::
sage: isinstance(T20, FiniteRankFreeModule) False
because `M = S^2` is not parallelizable::
sage: M.is_manifestly_parallelizable() False
On the contrary, the module of type-`(2,0)` tensor fields on `U` is a free module, since `U` is parallelizable (being a coordinate domain)::
sage: T20U = U.tensor_field_module((2,0)) sage: isinstance(T20U, FiniteRankFreeModule) True sage: U.is_manifestly_parallelizable() True
The zero element::
sage: z = T20.zero() ; z Tensor field zero of type (2,0) on the 2-dimensional differentiable manifold M sage: z is T20(0) True sage: z[c_xy.frame(),:] [0 0] [0 0] sage: z[c_uv.frame(),:] [0 0] [0 0]
The module `T^{(2,0)}(M)` coerces to any module of type-`(2,0)` tensor fields defined on some subdomain of `M`, for instance `T^{(2,0)}(U)`::
sage: T20U.has_coerce_map_from(T20) True
The reverse is not true::
sage: T20.has_coerce_map_from(T20U) False
The coercion::
sage: T20U.coerce_map_from(T20) Coercion map: From: Module T^(2,0)(M) of type-(2,0) tensors fields on the 2-dimensional differentiable manifold M To: Free module T^(2,0)(U) of type-(2,0) tensors fields on the Open subset U of the 2-dimensional differentiable manifold M
The coercion map is actually the *restriction* of tensor fields defined on `M` to `U`::
sage: t = M.tensor_field(2,0, name='t') sage: eU = c_xy.frame() ; eV = c_uv.frame() sage: t[eU,:] = [[2,0], [0,-3]] sage: t.add_comp_by_continuation(eV, W, chart=c_uv) sage: T20U(t) # the conversion map in action Tensor field t of type (2,0) on the Open subset U of the 2-dimensional differentiable manifold M sage: T20U(t) is t.restrict(U) True
There is also a coercion map from fields of tangent-space automorphisms to tensor fields of type-`(1,1)`::
sage: T11 = M.tensor_field_module((1,1)) ; T11 Module T^(1,1)(M) of type-(1,1) tensors fields on the 2-dimensional differentiable manifold M sage: GL = M.automorphism_field_group() ; GL General linear group of the Module X(M) of vector fields on the 2-dimensional differentiable manifold M sage: T11.has_coerce_map_from(GL) True
Explicit call to the coercion map::
sage: a = GL.one() ; a Field of tangent-space identity maps on the 2-dimensional differentiable manifold M sage: a.parent() General linear group of the Module X(M) of vector fields on the 2-dimensional differentiable manifold M sage: ta = T11.coerce(a) ; ta Tensor field Id of type (1,1) on the 2-dimensional differentiable manifold M sage: ta.parent() Module T^(1,1)(M) of type-(1,1) tensors fields on the 2-dimensional differentiable manifold M sage: ta[eU,:] # ta on U [1 0] [0 1] sage: ta[eV,:] # ta on V [1 0] [0 1]
"""
r""" Construct a module of tensor fields taking values on a (a priori) not parallelizable differentiable manifold.
TESTS::
sage: M = Manifold(2, 'M') # the 2-dimensional sphere S^2 sage: U = M.open_subset('U') # complement of the North pole sage: c_xy.<x,y> = U.chart() # stereographic coordinates from the North pole sage: V = M.open_subset('V') # complement of the South pole sage: c_uv.<u,v> = V.chart() # stereographic coordinates from the South pole sage: M.declare_union(U,V) # S^2 is the union of U and V sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)), ....: intersection_name='W', restrictions1= x^2+y^2!=0, ....: restrictions2= u^2+v^2!=0) sage: XM = M.vector_field_module() sage: from sage.manifolds.differentiable.tensorfield_module import TensorFieldModule sage: T21 = TensorFieldModule(XM, (2,1)); T21 Module T^(2,1)(M) of type-(2,1) tensors fields on the 2-dimensional differentiable manifold M sage: T21 is M.tensor_field_module((2,1)) True sage: TestSuite(T21).run(skip='_test_elements')
In the above test suite, ``_test_elements`` is skipped because of the ``_test_pickling`` error of the elements (to be fixed in :class:`~sage.manifolds.differentiable.tensorfield.TensorField`)
""" dm_name = dest_map._name dm_latex_name = dest_map._latex_name if dm_name is None: dm_name = "unnamed map" if dm_latex_name is None: dm_latex_name = r"\mathrm{unnamed\; map}" name += "," + dm_name latex_name += "," + dm_latex_name # the member self._ring is created for efficiency (to avoid calls to # self.base_ring()):
#### Parent methods
latex_name=None, sym=None, antisym=None): r""" Construct a tensor field.
TESTS::
sage: M = Manifold(2, 'M') sage: U = M.open_subset('U'); V = M.open_subset('V') sage: c_xy.<x,y> = U.chart(); c_uv.<u,v> = V.chart() sage: M.declare_union(U,V) sage: T20 = M.tensor_field_module((2,0)) sage: t = T20([[1+x, 2], [x*y, 3-y]], name='t'); t Tensor field t of type (2,0) on the 2-dimensional differentiable manifold M sage: t.display(c_xy.frame()) t = (x + 1) d/dx*d/dx + 2 d/dx*d/dy + x*y d/dy*d/dx + (-y + 3) d/dy*d/dy sage: T20(0) is T20.zero() True
""" # coercion of a p-form to a type-(0,p) tensor field: self._vmodule != form.base_module()): raise TypeError("cannot convert the {}".format(form) + " to an element of {}".format(self)) else: name=form._name, latex_name=form._latex_name, antisym=asym) # coercion of a p-vector field to a type-(p,0) tensor: self._vmodule != pvect.base_module()): raise TypeError("cannot convert the {}".format(pvect) + " to an element of {}".format(self)) asym = None else: name=pvect._name, latex_name=pvect._latex_name, antisym=asym) # coercion of an automorphism to a type-(1,1) tensor: self._vmodule != autom.base_module()): raise TypeError("cannot convert the {}".format(autom) + " to an element of {}".format(self)) name=autom._name, latex_name=autom._latex_name) # coercion by domain restriction if (self._tensor_type == comp._tensor_type and self._domain.is_subset(comp._domain) and self._ambient_domain.is_subset(comp._ambient_domain)): return comp.restrict(self._domain) else: raise TypeError("cannot convert the {}".format(comp) + " to an element of {}".format(self))
# standard construction name=name, latex_name=latex_name, sym=sym, antisym=antisym)
r""" Construct some (unnamed) tensor field.
TESTS::
sage: M = Manifold(2, 'M') sage: U = M.open_subset('U'); V = M.open_subset('V') sage: c_xy.<x,y> = U.chart(); c_uv.<u,v> = V.chart() sage: M.declare_union(U,V) sage: T31 = M.tensor_field_module((3,1)) sage: T31._an_element_() Tensor field of type (3,1) on the 2-dimensional differentiable manifold M
""" # Non-trivial open covers of the domain:
r""" Determine whether coercion to ``self`` exists from other parent.
TESTS::
sage: M = Manifold(2, 'M') sage: U = M.open_subset('U') sage: T02 = M.tensor_field_module((0,2)) sage: T02U = U.tensor_field_module((0,2)) sage: T02U._coerce_map_from_(T02) True sage: T02._coerce_map_from_(T02U) False sage: T02._coerce_map_from_(M.diff_form_module(2)) True sage: T20 = M.tensor_field_module((2,0)) sage: T20._coerce_map_from_(M.multivector_module(2)) True sage: T11 = M.tensor_field_module((1,1)) sage: T11._coerce_map_from_(M.automorphism_field_group()) True
""" DiffFormModule MultivectorModule import AutomorphismFieldGroup # coercion by domain restriction and self._domain.is_subset(other._domain) and self._ambient_domain.is_subset(other._ambient_domain)) # coercion of p-forms to type-(0,p) tensor fields and self._tensor_type == (0, other.degree())) # coercion of p-vector fields to type-(p,0) tensor fields and self._tensor_type == (other.degree(),0)) # coercion of automorphism fields to type-(1,1) tensor fields and self._tensor_type == (1,1))
#### End of parent methods
r""" Return a string representation of ``self``.
TESTS::
sage: M = Manifold(2, 'M') sage: T13 = M.tensor_field_module((1,3)) sage: T13._repr_() 'Module T^(1,3)(M) of type-(1,3) tensors fields on the 2-dimensional differentiable manifold M' sage: repr(T13) # indirect doctest 'Module T^(1,3)(M) of type-(1,3) tensors fields on the 2-dimensional differentiable manifold M' sage: T13 # indirect doctest Module T^(1,3)(M) of type-(1,3) tensors fields on the 2-dimensional differentiable manifold M
""" self._tensor_type[1]) else: description += "along the {}".format(self._domain) + \ " mapped into the {}".format(self._ambient_domain)
r""" Return a LaTeX representation of ``self``.
TESTS::
sage: M = Manifold(2, 'M') sage: T13 = M.tensor_field_module((1,3)) sage: T13._latex_() '\\mathcal{T}^{(1,3)}\\left(M\\right)' sage: latex(T13) # indirect doctest \mathcal{T}^{(1,3)}\left(M\right)
""" return r'\mbox{' + str(self) + r'}' else:
r""" Return the vector field module on which ``self`` is constructed.
OUTPUT:
- a :class:`~sage.manifolds.differentiable.vectorfield_module.VectorFieldModule` representing the module on which ``self`` is defined
EXAMPLES::
sage: M = Manifold(2, 'M') sage: T13 = M.tensor_field_module((1,3)) sage: T13.base_module() Module X(M) of vector fields on the 2-dimensional differentiable manifold M sage: T13.base_module() is M.vector_field_module() True sage: T13.base_module().base_ring() Algebra of differentiable scalar fields on the 2-dimensional differentiable manifold M
"""
r""" Return the tensor type of ``self``.
OUTPUT:
- pair `(k,l)` of non-negative integers such that the tensor fields belonging to this module are of type `(k,l)`
EXAMPLES::
sage: M = Manifold(2, 'M') sage: T13 = M.tensor_field_module((1,3)) sage: T13.tensor_type() (1, 3) sage: T20 = M.tensor_field_module((2,0)) sage: T20.tensor_type() (2, 0)
"""
def zero(self): """ Return the zero of ``self``.
TESTS::
sage: M = Manifold(2, 'M') sage: U = M.open_subset('U'); V = M.open_subset('V') sage: c_xy.<x,y> = U.chart(); c_uv.<u,v> = V.chart() sage: M.declare_union(U,V) sage: T20 = M.tensor_field_module((2,0)) sage: T20.zero() Tensor field zero of type (2,0) on the 2-dimensional differentiable manifold M """ name='zero', latex_name='0', sym=None, antisym=None) # (since new components are initialized to zero)
#***********************************************************************
r""" Free module of tensor fields of a given type `(k,l)` along a differentiable manifold `U` with values on a parallelizable manifold `M`, via a differentiable map `U \rightarrow M`.
Given two non-negative integers `k` and `l` and a differentiable map
.. MATH::
\Phi:\ U \longrightarrow M,
the *tensor field module* `T^{(k,l)}(U, \Phi)` is the set of all tensor fields of the type
.. MATH::
t:\ U \longrightarrow T^{(k,l)} M
(where `T^{(k,l)}M` is the tensor bundle of type `(k,l)` over `M`) such that
.. MATH::
t(p) \in T^{(k,l)}(T_{\Phi(p)}M)
for all `p \in U`, i.e. `t(p)` is a tensor of type `(k,l)` on the tangent vector space `T_{\Phi(p)}M`. Since `M` is parallelizable, the set `T^{(k,l)}(U,\Phi)` is a free module over `C^k(U)`, the ring (algebra) of differentiable scalar fields on `U` (see :class:`~sage.manifolds.differentiable.scalarfield_algebra.DiffScalarFieldAlgebra`).
The standard case of tensor fields *on* a differentiable manifold corresponds to `U = M` and `\Phi = \mathrm{Id}_M`; we then denote `T^{(k,l)}(M,\mathrm{Id}_M)` by merely `T^{(k,l)}(M)`. Other common cases are `\Phi` being an immersion and `\Phi` being a curve in `M` (`U` is then an open interval of `\RR`).
.. NOTE::
If `M` is not parallelizable, the class :class:`TensorFieldModule` should be used instead, for `T^{(k,l)}(U,\Phi)` is no longer a free module.
INPUT:
- ``vector_field_module`` -- free module `\mathfrak{X}(U,\Phi)` of vector fields along `U` associated with the map `\Phi: U \rightarrow M` - ``tensor_type`` -- pair `(k,l)` with `k` being the contravariant rank and `l` the covariant rank
EXAMPLES:
Module of type-`(2,0)` tensor fields on `\RR^3`::
sage: M = Manifold(3, 'R^3') sage: c_xyz.<x,y,z> = M.chart() # Cartesian coordinates sage: T20 = M.tensor_field_module((2,0)) ; T20 Free module T^(2,0)(R^3) of type-(2,0) tensors fields on the 3-dimensional differentiable manifold R^3
`T^{(2,0)}(\RR^3)` is a module over the algebra `C^k(\RR^3)`::
sage: T20.category() Category of finite dimensional modules over Algebra of differentiable scalar fields on the 3-dimensional differentiable manifold R^3 sage: T20.base_ring() is M.scalar_field_algebra() True
`T^{(2,0)}(\RR^3)` is a free module::
sage: isinstance(T20, FiniteRankFreeModule) True
because `M = \RR^3` is parallelizable::
sage: M.is_manifestly_parallelizable() True
The zero element::
sage: z = T20.zero() ; z Tensor field zero of type (2,0) on the 3-dimensional differentiable manifold R^3 sage: z[:] [0 0 0] [0 0 0] [0 0 0]
A random element::
sage: t = T20.an_element() ; t Tensor field of type (2,0) on the 3-dimensional differentiable manifold R^3 sage: t[:] [2 0 0] [0 0 0] [0 0 0]
The module `T^{(2,0)}(\RR^3)` coerces to any module of type-`(2,0)` tensor fields defined on some subdomain of `\RR^3`::
sage: U = M.open_subset('U', coord_def={c_xyz: x>0}) sage: T20U = U.tensor_field_module((2,0)) sage: T20U.has_coerce_map_from(T20) True sage: T20.has_coerce_map_from(T20U) # the reverse is not true False sage: T20U.coerce_map_from(T20) Coercion map: From: Free module T^(2,0)(R^3) of type-(2,0) tensors fields on the 3-dimensional differentiable manifold R^3 To: Free module T^(2,0)(U) of type-(2,0) tensors fields on the Open subset U of the 3-dimensional differentiable manifold R^3
The coercion map is actually the *restriction* of tensor fields defined on `\RR^3` to `U`.
There is also a coercion map from fields of tangent-space automorphisms to tensor fields of type `(1,1)`::
sage: T11 = M.tensor_field_module((1,1)) ; T11 Free module T^(1,1)(R^3) of type-(1,1) tensors fields on the 3-dimensional differentiable manifold R^3 sage: GL = M.automorphism_field_group() ; GL General linear group of the Free module X(R^3) of vector fields on the 3-dimensional differentiable manifold R^3 sage: T11.has_coerce_map_from(GL) True
An explicit call to this coercion map is::
sage: id = GL.one() ; id Field of tangent-space identity maps on the 3-dimensional differentiable manifold R^3 sage: tid = T11(id) ; tid Tensor field Id of type (1,1) on the 3-dimensional differentiable manifold R^3 sage: tid[:] [1 0 0] [0 1 0] [0 0 1]
"""
r""" Construct a module of tensor fields taking values on a parallelizable differentiable manifold.
TESTS::
sage: M = Manifold(2, 'M') sage: X.<x,y> = M.chart() # makes M parallelizable sage: XM = M.vector_field_module() sage: from sage.manifolds.differentiable.tensorfield_module import TensorFieldFreeModule sage: T12 = TensorFieldFreeModule(XM, (1,2)); T12 Free module T^(1,2)(M) of type-(1,2) tensors fields on the 2-dimensional differentiable manifold M sage: T12 is M.tensor_field_module((1,2)) True sage: TestSuite(T12).run()
""" lcov, domain._latex_name) dm_name = "unnamed map" dm_latex_name = r"\mathrm{unnamed\; map}" name=name, latex_name=latex_name)
#### Parent methods
latex_name=None, sym=None, antisym=None): r""" Construct a tensor field.
TESTS::
sage: M = Manifold(2, 'M') sage: X.<x,y> = M.chart() # makes M parallelizable sage: T12 = M.tensor_field_module((1,2)) sage: t = T12([[[x,-y], [2,y]], [[1+x,y^2], [x^2,3]], ....: [[x*y, 1-x], [y^2, x]]], name='t'); t Tensor field t of type (1,2) on the 2-dimensional differentiable manifold M sage: t.display() t = x d/dx*dx*dx - y d/dx*dx*dy + 2 d/dx*dy*dx + y d/dx*dy*dy + (x + 1) d/dy*dx*dx + y^2 d/dy*dx*dy + x^2 d/dy*dy*dx + 3 d/dy*dy*dy sage: T12(0) is T12.zero() True
""" # coercion of a p-form to a type-(0,p) tensor field: self._fmodule != form.base_module()): raise TypeError("cannot convert the {}".format(form) + " to an element of {}".format(self)) else: name=form._name, latex_name=form._latex_name, antisym=asym) # coercion of a p-vector field to a type-(p,0) tensor field: self._fmodule != pvect.base_module()): raise TypeError("cannot convert the {}".format(pvect) + " to an element of {}".format(self)) asym = None else: name=pvect._name, latex_name=pvect._latex_name, antisym=asym) # coercion of an automorphism to a type-(1,1) tensor: self._fmodule != autom.base_module()): raise TypeError("cannot convert the {}".format(autom) + " to an element of {}".format(self)) name=autom._name, latex_name=autom._latex_name) # coercion by domain restriction and self._domain.is_subset(comp._domain) and self._ambient_domain.is_subset( comp._ambient_domain)): else: raise TypeError("cannot convert the {}".format(comp) + " to an element of {}".format(self)) # Standard construction name=name, latex_name=latex_name, sym=sym, antisym=antisym)
# Rem: _an_element_ is declared in the superclass TensorFreeModule
r""" Determine whether coercion to ``self`` exists from other parent.
TESTS::
sage: M = Manifold(2, 'M') sage: X.<x,y> = M.chart() # makes M parallelizable sage: U = M.open_subset('U', coord_def={X: x>0}) sage: T02 = M.tensor_field_module((0,2)) sage: T02U = U.tensor_field_module((0,2)) sage: T02U._coerce_map_from_(T02) True sage: T02._coerce_map_from_(T02U) False sage: T02._coerce_map_from_(M.diff_form_module(2)) True sage: T20 = M.tensor_field_module((2,0)) sage: T20._coerce_map_from_(M.multivector_module(2)) True sage: T11 = M.tensor_field_module((1,1)) sage: T11._coerce_map_from_(M.automorphism_field_group()) True
""" DiffFormFreeModule MultivectorFreeModule import AutomorphismFieldParalGroup # coercion by domain restriction and self._domain.is_subset(other._domain) and self._ambient_domain.is_subset(other._ambient_domain)) # coercion of p-forms to type-(0,p) tensor fields and self._tensor_type == (0, other.degree())) # coercion of p-vector fields to type-(p,0) tensor fields and self._tensor_type == (other.degree(),0)) # coercion of automorphism fields to type-(1,1) tensor fields and self._tensor_type == (1,1))
#### End of parent methods
r""" Return a string representation of ``self``.
TESTS::
sage: M = Manifold(2, 'M') sage: X.<x,y> = M.chart() # makes M parallelizable sage: T12 = M.tensor_field_module((1,2)) sage: T12._repr_() 'Free module T^(1,2)(M) of type-(1,2) tensors fields on the 2-dimensional differentiable manifold M' sage: repr(T12) # indirect doctest 'Free module T^(1,2)(M) of type-(1,2) tensors fields on the 2-dimensional differentiable manifold M' sage: T12 # indirect doctest Free module T^(1,2)(M) of type-(1,2) tensors fields on the 2-dimensional differentiable manifold M
""" self._tensor_type[1]) else: " mapped into the {}".format(self._ambient_domain)
|