Skip to content
This repository was archived by the owner on Jan 30, 2023. It is now read-only.

Commit 178c1ca

Browse files
committed
Update Schouten and Cotton tensors to the latest version of the dependency ticket #19209
2 parents c622eb9 + a641f90 commit 178c1ca

File tree

1 file changed

+194
-12
lines changed

1 file changed

+194
-12
lines changed

src/sage/manifolds/differentiable/metric.py

Lines changed: 194 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
AUTHORS:
1010
1111
- Eric Gourgoulhon, Michal Bejger (2013-2015) : initial version
12+
- Pablo Angulo (2016): Schouten, Cotton and Cotton-York tensors
1213
1314
REFERENCES:
1415
@@ -20,6 +21,7 @@
2021
#******************************************************************************
2122
# Copyright (C) 2015 Eric Gourgoulhon <[email protected]>
2223
# Copyright (C) 2015 Michal Bejger <[email protected]>
24+
# Copyright (C) 2016 Pablo Angulo <[email protected]>
2325
#
2426
# Distributed under the terms of the GNU General Public License (GPL)
2527
# as published by the Free Software Foundation; either version 2 of
@@ -312,6 +314,9 @@ class PseudoRiemannianMetric(TensorField):
312314
True
313315
314316
"""
317+
_derived_objects = ('_connection', '_ricci_scalar', '_weyl',
318+
'_schouten', '_cotton', '_cotton_york')
319+
315320
def __init__(self, vector_field_module, name, signature=None,
316321
latex_name=None):
317322
r"""
@@ -441,9 +446,8 @@ def _init_derived(self):
441446
self._inverse = self._vmodule.tensor((2,0), name=inv_name,
442447
latex_name=inv_latex_name,
443448
sym=(0,1))
444-
self._connection = None # Levi-Civita connection (not set yet)
445-
self._ricci_scalar = None # Ricci scalar (not set yet)
446-
self._weyl = None # Weyl tensor (not set yet)
449+
for attr in self._derived_objects:
450+
self.__setattr__(attr, None)
447451
self._determinants = {} # determinants in various frames
448452
self._sqrt_abs_dets = {} # sqrt(abs(det g)) in various frames
449453
self._vol_forms = [] # volume form and associated tensors
@@ -464,9 +468,9 @@ def _del_derived(self):
464468
# The inverse metric is cleared:
465469
self._del_inverse()
466470
# The connection, Ricci scalar and Weyl tensor are reset to None:
467-
self._connection = None
468-
self._ricci_scalar = None
469-
self._weyl = None
471+
# The Schouten, Cotton and Cotton-York tensors are reset to None:
472+
for attr in self._derived_objects:
473+
self.__setattr__(attr, None)
470474
# The dictionary of determinants over the various frames is cleared:
471475
self._determinants.clear()
472476
self._sqrt_abs_dets.clear()
@@ -563,12 +567,10 @@ def restrict(self, subdomain, dest_map=None):
563567
resu._indic_signat = self._indic_signat
564568
# Restrictions of derived quantities:
565569
resu._inverse = self.inverse().restrict(subdomain)
566-
if self._connection is not None:
567-
resu._connection = self._connection.restrict(subdomain)
568-
if self._ricci_scalar is not None:
569-
resu._ricci_scalar = self._ricci_scalar.restrict(subdomain)
570-
if self._weyl is not None:
571-
resu._weyl = self._weyl.restrict(subdomain)
570+
for attr in self._derived_objects:
571+
derived = self.__getattribute__(attr)
572+
if derived is not None:
573+
resu.__setattr__(attr, derived.restrict(subdomain))
572574
if self._vol_forms != []:
573575
for eps in self._vol_forms:
574576
resu._vol_forms.append(eps.restrict(subdomain))
@@ -1183,6 +1185,186 @@ def weyl(self, name=None, latex_name=None):
11831185
self._weyl.set_name(name=name, latex_name=latex_name)
11841186
return self._weyl
11851187

1188+
def schouten(self, name=None, latex_name=None):
1189+
r"""
1190+
Return the Schouten tensor associated with the metric.
1191+
1192+
The Schouten tensor is the tensor field `Sc` of type (0,2) defined
1193+
from the Ricci curvature tensor `Ric` (see :meth:`ricci`) and the
1194+
scalar curvature `r` (see :meth:`ricci_scalar`) and the metric `g` by
1195+
1196+
.. MATH::
1197+
1198+
Sc(u, v) = \frac{1}{n-2}\left(Ric(u, v) + \frac{r}{2(n-1)}g(u,v)
1199+
\right)
1200+
1201+
for any vector fields `u` and `v`.
1202+
1203+
INPUT:
1204+
1205+
- ``name`` -- (default: ``None``) name given to the Schouten tensor;
1206+
if none, it is set to "Schouten(g)", where "g" is the metric's name
1207+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
1208+
Schouten tensor; if none, it is set to "\\mathrm{Schouten}(g)",
1209+
where "g" is the metric's name
1210+
1211+
OUTPUT:
1212+
1213+
- the Schouten tensor `Sc`, as an instance of
1214+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField` of tensor
1215+
type (0,2) and symmetric
1216+
1217+
EXAMPLES:
1218+
1219+
Schouten tensor of the left invariant metric of Heisenberg's
1220+
Nil group::
1221+
1222+
sage: M = Manifold(3, 'Nil', start_index=1)
1223+
sage: X.<x,y,z> = M.chart()
1224+
sage: g = M.riemannian_metric('g')
1225+
sage: g[1,1], g[2,2], g[2,3], g[3,3] = 1, 1+x^2, -x, 1
1226+
sage: g.display()
1227+
g = dx*dx + (x^2 + 1) dy*dy - x dy*dz - x dz*dy + dz*dz
1228+
sage: g.schouten()
1229+
Field of symmetric bilinear forms Schouten(g) on the 3-dimensional
1230+
differentiable manifold Nil
1231+
sage: g.schouten().display()
1232+
Schouten(g) = -3/8 dx*dx + (5/8*x^2 - 3/8) dy*dy - 5/8*x dy*dz
1233+
- 5/8*x dz*dy + 5/8 dz*dz
1234+
1235+
"""
1236+
n = self._ambient_domain.dimension()
1237+
if n < 3:
1238+
raise ValueError("the Schouten tensor is only defined for a " +
1239+
"manifold of dimension >= 3")
1240+
if self._schouten is None:
1241+
s = (1/(n-2))*self.ricci() - (self.ricci_scalar()/(2*(n-1)*(n-2)))*self
1242+
name = name or 'Schouten(' + self._name + ')'
1243+
latex_name = latex_name or r'\mathrm{Schouten}(' + self._latex_name + ')'
1244+
s.set_name(name=name, latex_name=latex_name)
1245+
self._schouten = s
1246+
return self._schouten
1247+
1248+
def cotton(self, name=None, latex_name=None):
1249+
r"""
1250+
Return the Cotton conformal tensor associated with the metric.
1251+
The tensor has type (0,3) and is defined in terms of the Schouten
1252+
tensor `S` (see :meth:`schouten`):
1253+
1254+
.. MATH::
1255+
1256+
C_{ijk} = (n-2) \left(\nabla_k S_{ij}
1257+
- \nabla_j S_{ik}\right)
1258+
1259+
INPUT:
1260+
1261+
- ``name`` -- (default: ``None``) name given to the Cotton conformal
1262+
tensor; if ``None``, it is set to "Cot(g)", where "g" is the metric's
1263+
name
1264+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
1265+
Cotton conformal tensor; if ``None``, it is set to "\\mathrm{Cot}(g)",
1266+
where "g" is the metric's name
1267+
1268+
OUTPUT:
1269+
1270+
- the Cotton conformal tensor `Cot`, as an instance of
1271+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField`
1272+
1273+
EXAMPLES:
1274+
1275+
Checking that the Cotton tensor identically vanishes on a conformally flat
1276+
3-dimensional manifold, for instance the hyperbolic space `H^3`::
1277+
1278+
sage: M = Manifold(3, 'H^3', start_index=1)
1279+
sage: U = M.open_subset('U') # the complement of the half-plane (y=0, x>=0)
1280+
sage: X.<rh,th,ph> = U.chart(r'rh:(0,+oo):\rho th:(0,pi):\theta ph:(0,2*pi):\phi')
1281+
sage: g = U.metric('g')
1282+
sage: b = var('b')
1283+
sage: g[1,1], g[2,2], g[3,3] = b^2, (b*sinh(rh))^2, (b*sinh(rh)*sin(th))^2
1284+
sage: g.display() # standard metric on H^3:
1285+
g = b^2 drh*drh + b^2*sinh(rh)^2 dth*dth
1286+
+ b^2*sin(th)^2*sinh(rh)^2 dph*dph
1287+
sage: Cot = g.cotton() ; Cot # long time
1288+
Tensor field Cot(g) of type (0,3) on the Open subset U of the
1289+
3-dimensional differentiable manifold H^3
1290+
sage: Cot == 0 # long time
1291+
True
1292+
1293+
"""
1294+
n = self._ambient_domain.dimension()
1295+
if n < 3:
1296+
raise ValueError("the Cotton tensor is only defined for a " +
1297+
"manifold of dimension >= 3")
1298+
if self._cotton is None:
1299+
nabla = self.connection()
1300+
s = self.schouten()
1301+
cot = 2*(n-2)*nabla(s).antisymmetrize(1,2)
1302+
name = name or 'Cot(' + self._name + ')'
1303+
latex_name = latex_name or r'\mathrm{Cot}(' + self._latex_name + ')'
1304+
cot.set_name(name=name, latex_name=latex_name)
1305+
self._cotton = cot
1306+
return self._cotton
1307+
1308+
def cotton_york(self, name=None, latex_name=None):
1309+
r"""
1310+
Return the Cotton-York conformal tensor associated with the metric.
1311+
The tensor has type (0,2) and is only defined for manifolds of
1312+
dimension 3. It is defined in terms of the Cotton tensor `C`
1313+
(see :meth:`cotton`) or the Schouten tensor `S` (see :meth:`schouten`):
1314+
1315+
.. MATH::
1316+
1317+
CY_{ij} = \frac{1}{2} \epsilon^{kl}_{\ \ \, i} C_{jlk}
1318+
= \epsilon^{kl}_{\ \ \, i} \nabla_k S_{lj}
1319+
1320+
INPUT:
1321+
1322+
- ``name`` -- (default: ``None``) name given to the Cotton-York
1323+
tensor; if ``None``, it is set to "CY(g)", where "g" is the metric's
1324+
name
1325+
- ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
1326+
Cotton-York tensor; if ``None``, it is set to "\\mathrm{CY}(g)",
1327+
where "g" is the metric's name
1328+
1329+
OUTPUT:
1330+
1331+
- the Cotton-York conformal tensor `CY`, as an instance of
1332+
:class:`~sage.manifolds.differentiable.tensorfield.TensorField`
1333+
1334+
EXAMPLES:
1335+
1336+
Compute the determinant of the Cotton-York tensor for the Heisenberg
1337+
group with the left invariant metric::
1338+
1339+
sage: M = Manifold(3, 'Nil', start_index=1)
1340+
sage: X.<x,y,z> = M.chart()
1341+
sage: g = M.riemannian_metric('g')
1342+
sage: g[1,1], g[2,2], g[2,3], g[3,3] = 1, 1+x^2, -x, 1
1343+
sage: g.display()
1344+
g = dx*dx + (x^2 + 1) dy*dy - x dy*dz - x dz*dy + dz*dz
1345+
sage: CY = g.cotton_york() ; CY # long time
1346+
Tensor field CY(g) of type (0,2) on the 3-dimensional
1347+
differentiable manifold Nil
1348+
sage: CY.display() # long time
1349+
CY(g) = 1/2 dx*dx + (-x^2 + 1/2) dy*dy + x dy*dz + x dz*dy - dz*dz
1350+
sage: det(CY[:]) # long time
1351+
-1/4
1352+
1353+
"""
1354+
n = self._ambient_domain.dimension()
1355+
if n != 3:
1356+
raise ValueError("the Cotton-York tensor is only defined for a " +
1357+
"manifold of dimension 3")
1358+
if self._cotton_york is None:
1359+
cot = self.cotton()
1360+
eps = self.volume_form(2)
1361+
cy = eps.contract(0, 1, cot, 2, 1)/2
1362+
name = name or 'CY(' + self._name + ')'
1363+
latex_name = latex_name or r'\mathrm{CY}(' + self._latex_name + ')'
1364+
cy.set_name(name=name, latex_name=latex_name)
1365+
self._cotton_york = cy
1366+
return self._cotton_york
1367+
11861368
def determinant(self, frame=None):
11871369
r"""
11881370
Determinant of the metric components in the specified frame.

0 commit comments

Comments
 (0)