def hodge_star(self, metric): r""" Compute the Hodge dual of the differential form. If ``self`` is a `p`-form `A`, its Hodge dual is the `(n-p)`-form `*A` defined by (`n` being the manifold's dimension) .. MATH:: *A_{i_1\ldots i_{n-p}} = \frac{1}{p!} A_{k_1\ldots k_p} \epsilon^{k_1\ldots k_p}_{\qquad\ i_1\ldots i_{n-p}} where $\epsilon$ is the volume form associated with some pseudo-Riemannian metric `g` on the manifold, and the indices `k_1,\ldots, k_p` are raised with `g`. INPUT: - ``metric``: the pseudo-Riemannian metric `g` defining the Hodge dual, via the volume form `\epsilon`; must be an instance of :class:`Metric` OUTPUT: - the `(n-p)`-form `*A` EXAMPLES: Hodge star of a 1-form in the Euclidean space `R^3`:: sage: m = Manifold(3, 'M', start_index=1) sage: X.<x,y,z> = m.chart('x y z', 'xyz') sage: g = Metric(m, 'g') sage: g[1,1], g[2,2], g[3,3] = 1, 1, 1 sage: a = OneForm(m, 'A') sage: var('Ax Ay Az') (Ax, Ay, Az) sage: a[:] = (Ax, Ay, Az) sage: sa = a.hodge_star(g) ; sa 2-form '*A' on the 3-dimensional manifold 'M' sage: sa.view() *A = Az dx/\dy - Ay dx/\dz + Ax dy/\dz sage: ssa = sa.hodge_star(g) ; ssa 1-form '**A' on the 3-dimensional manifold 'M' sage: ssa.view() **A = Ax dx + Ay dy + Az dz sage: ssa == a # must hold for a Riemannian metric in dimension 3 True Hodge star of a 0-form (scalar field) in `R^3`:: sage: f = ScalarField(m, function('F',x,y,z), name='f') sage: sf = f.hodge_star(g) ; sf 3-form '*f' on the 3-dimensional manifold 'M' sage: sf.view() *f = F(x, y, z) dx/\dy/\dz sage: ssf = sf.hodge_star(g) ; ssf scalar field '**f' on the 3-dimensional manifold 'M' sage: ssf.view() **f: (x, y, z) |--> F(x, y, z) sage: ssf == f # must hold for a Riemannian metric True Hodge star of a 0-form in Minkowksi spacetime:: sage: m = Manifold(4, 'M') sage: X = m.chart('t x y z', 'txyz') sage: g = Metric(m, 'g', signature=2) sage: g[0,0], g[1,1], g[2,2], g[3,3] = -1, 1, 1, 1 sage: g.view() # Minkowski metric g = -dt*dt + dx*dx + dy*dy + dz*dz sage: var('f0') f0 sage: f = ScalarField(m, f0, name='f') sage: sf = f.hodge_star(g) ; sf 4-form '*f' on the 4-dimensional manifold 'M' sage: sf.view() *f = f0 dt/\dx/\dy/\dz sage: ssf = sf.hodge_star(g) ; ssf scalar field '**f' on the 4-dimensional manifold 'M' sage: ssf.view() **f: (t, x, y, z) |--> -f0 sage: ssf == -f # must hold for a Lorentzian metric True Hodge star of a 1-form in Minkowksi spacetime:: sage: a = OneForm(m, 'A') sage: var('At Ax Ay Az') (At, Ax, Ay, Az) sage: a[:] = (At, Ax, Ay, Az) sage: a.view() A = At dt + Ax dx + Ay dy + Az dz sage: sa = a.hodge_star(g) ; sa 3-form '*A' on the 4-dimensional manifold 'M' sage: sa.view() *A = -Az dt/\dx/\dy + Ay dt/\dx/\dz - Ax dt/\dy/\dz - At dx/\dy/\dz sage: ssa = sa.hodge_star(g) ; ssa 1-form '**A' on the 4-dimensional manifold 'M' sage: ssa.view() **A = At dt + Ax dx + Ay dy + Az dz sage: ssa == a # must hold for a Lorentzian metric in dimension 4 True Hodge star of a 2-form in Minkowksi spacetime:: sage: F = DiffForm(m, 2, 'F') sage: var('Ex Ey Ez Bx By Bz') (Ex, Ey, Ez, Bx, By, Bz) sage: F[0,1], F[0,2], F[0,3] = -Ex, -Ey, -Ez sage: F[1,2], F[1,3], F[2,3] = Bz, -By, Bx sage: F[:] [ 0 -Ex -Ey -Ez] [ Ex 0 Bz -By] [ Ey -Bz 0 Bx] [ Ez By -Bx 0] sage: sF = F.hodge_star(g) ; sF 2-form '*F' on the 4-dimensional manifold 'M' sage: sF[:] [ 0 Bx By Bz] [-Bx 0 Ez -Ey] [-By -Ez 0 Ex] [-Bz Ey -Ex 0] sage: ssF = sF.hodge_star(g) ; ssF 2-form '**F' on the 4-dimensional manifold 'M' sage: ssF[:] [ 0 Ex Ey Ez] [-Ex 0 -Bz By] [-Ey Bz 0 -Bx] [-Ez -By Bx 0] sage: ssF.view() **F = Ex dt/\dx + Ey dt/\dy + Ez dt/\dz - Bz dx/\dy + By dx/\dz - Bx dy/\dz sage: F.view() F = -Ex dt/\dx - Ey dt/\dy - Ez dt/\dz + Bz dx/\dy - By dx/\dz + Bx dy/\dz sage: ssF == -F # must hold for a Lorentzian metric in dimension 4 True Test of the standard identity .. MATH:: *(A\wedge B) = \epsilon(A^\sharp, B^\sharp, ., .) where `A` and `B` are any 1-forms and `A^\sharp` and `B^\sharp` the vectors associated to them by the metric `g` (index raising):: sage: b = OneForm(m, 'B') sage: var('Bt Bx By Bz') (Bt, Bx, By, Bz) sage: b[:] = (Bt, Bx, By, Bz) ; b.view() B = Bt dt + Bx dx + By dy + Bz dz sage: epsilon = g.volume_form() sage: (a.wedge(b)).hodge_star(g) == epsilon.contract(0, a.up(g), 0).contract(0, b.up(g), 0) True """ from sage.functions.other import factorial from utilities import format_unop_txt, format_unop_latex p = self.rank eps = metric.volume_form(p) if p == 0: resu = self * eps else: resu = self.contract(0, eps, 0) for j in range(1, p): resu = resu.self_contract(0, p-j) if p > 1: resu = resu / factorial(p) # Name and LaTeX name of the result: resu.name = format_unop_txt('*', self.name) resu.latex_name = format_unop_latex(r'\star ', self.latex_name) return resu
def hodge_star(self, metric): r""" Compute the Hodge dual of the differential form. If ``self`` is a `p`-form `A`, its Hodge dual is the `(n-p)`-form `*A` defined by (`n` being the manifold's dimension) .. MATH:: *A_{i_1\ldots i_{n-p}} = \frac{1}{p!} A_{k_1\ldots k_p} \epsilon^{k_1\ldots k_p}_{\qquad\ i_1\ldots i_{n-p}} where $\epsilon$ is the volume form associated with some pseudo-Riemannian metric `g` on the manifold, and the indices `k_1,\ldots, k_p` are raised with `g`. INPUT: - ``metric``: the pseudo-Riemannian metric `g` defining the Hodge dual, via the volume form `\epsilon`; must be an instance of :class:`Metric` OUTPUT: - the `(n-p)`-form `*A` EXAMPLES: Hodge star of a 1-form in the Euclidean space `R^3`:: sage: m = Manifold(3, 'M', start_index=1) sage: X = Chart(m, 'x y z', 'xyz') sage: g = Metric(m, 'g') sage: g[1,1], g[2,2], g[3,3] = 1, 1, 1 sage: a = OneForm(m, 'A') sage: var('Ax Ay Az') (Ax, Ay, Az) sage: a[:] = (Ax, Ay, Az) sage: sa = a.hodge_star(g) ; sa 2-form '*A' on the 3-dimensional manifold 'M' sage: sa.show() *A = Az dx/\dy - Ay dx/\dz + Ax dy/\dz sage: ssa = sa.hodge_star(g) ; ssa 1-form '**A' on the 3-dimensional manifold 'M' sage: ssa.show() **A = Ax dx + Ay dy + Az dz sage: ssa == a # must hold for a Riemannian metric in dimension 3 True Hodge star of a 0-form (scalar field) in `R^3`:: sage: f = ScalarField(m, function('F',x,y,z), name='f') sage: sf = f.hodge_star(g) ; sf 3-form '*f' on the 3-dimensional manifold 'M' sage: sf.show() *f = F(x, y, z) dx/\dy/\dz sage: ssf = sf.hodge_star(g) ; ssf scalar field '**f' on the 3-dimensional manifold 'M' sage: ssf.show() **f: (x, y, z) |--> F(x, y, z) sage: ssf == f # must hold for a Riemannian metric True Hodge star of a 0-form in Minkowksi spacetime:: sage: m = Manifold(4, 'M') sage: X = Chart(m, 't x y z', 'txyz') sage: g = Metric(m, 'g', signature=2) sage: g[0,0], g[1,1], g[2,2], g[3,3] = -1, 1, 1, 1 sage: g.show() # Minkowski metric g = -dt*dt + dx*dx + dy*dy + dz*dz sage: var('f0') f0 sage: f = ScalarField(m, f0, name='f') sage: sf = f.hodge_star(g) ; sf 4-form '*f' on the 4-dimensional manifold 'M' sage: sf.show() *f = f0 dt/\dx/\dy/\dz sage: ssf = sf.hodge_star(g) ; ssf scalar field '**f' on the 4-dimensional manifold 'M' sage: ssf.show() **f: (t, x, y, z) |--> -f0 sage: ssf == -f # must hold for a Lorentzian metric True Hodge star of a 1-form in Minkowksi spacetime:: sage: a = OneForm(m, 'A') sage: var('At Ax Ay Az') (At, Ax, Ay, Az) sage: a[:] = (At, Ax, Ay, Az) sage: a.show() A = At dt + Ax dx + Ay dy + Az dz sage: sa = a.hodge_star(g) ; sa 3-form '*A' on the 4-dimensional manifold 'M' sage: sa.show() *A = -Az dt/\dx/\dy + Ay dt/\dx/\dz - Ax dt/\dy/\dz - At dx/\dy/\dz sage: ssa = sa.hodge_star(g) ; ssa 1-form '**A' on the 4-dimensional manifold 'M' sage: ssa.show() **A = At dt + Ax dx + Ay dy + Az dz sage: ssa == a # must hold for a Lorentzian metric in dimension 4 True Hodge star of a 2-form in Minkowksi spacetime:: sage: F = DiffForm(m, 2, 'F') sage: var('Ex Ey Ez Bx By Bz') (Ex, Ey, Ez, Bx, By, Bz) sage: F[0,1], F[0,2], F[0,3] = -Ex, -Ey, -Ez sage: F[1,2], F[1,3], F[2,3] = Bz, -By, Bx sage: F[:] [ 0 -Ex -Ey -Ez] [ Ex 0 Bz -By] [ Ey -Bz 0 Bx] [ Ez By -Bx 0] sage: sF = F.hodge_star(g) ; sF 2-form '*F' on the 4-dimensional manifold 'M' sage: sF[:] [ 0 Bx By Bz] [-Bx 0 Ez -Ey] [-By -Ez 0 Ex] [-Bz Ey -Ex 0] sage: ssF = sF.hodge_star(g) ; ssF 2-form '**F' on the 4-dimensional manifold 'M' sage: ssF[:] [ 0 Ex Ey Ez] [-Ex 0 -Bz By] [-Ey Bz 0 -Bx] [-Ez -By Bx 0] sage: ssF.show() **F = Ex dt/\dx + Ey dt/\dy + Ez dt/\dz - Bz dx/\dy + By dx/\dz - Bx dy/\dz sage: F.show() F = -Ex dt/\dx - Ey dt/\dy - Ez dt/\dz + Bz dx/\dy - By dx/\dz + Bx dy/\dz sage: ssF == -F # must hold for a Lorentzian metric in dimension 4 True Test of the standard identity .. MATH:: *(A\wedge B) = \epsilon(A^\sharp, B^\sharp, ., .) where `A` and `B` are any 1-forms and `A^\sharp` and `B^\sharp` the vectors associated to them by the metric `g` (index raising):: sage: b = OneForm(m, 'B') sage: var('Bt Bx By Bz') (Bt, Bx, By, Bz) sage: b[:] = (Bt, Bx, By, Bz) ; b.show() B = Bt dt + Bx dx + By dy + Bz dz sage: epsilon = g.volume_form() sage: (a.wedge(b)).hodge_star(g) == epsilon.contract(0, a.up(g), 0).contract(0, b.up(g), 0) True """ from sage.functions.other import factorial from utilities import format_unop_txt, format_unop_latex p = self.rank eps = metric.volume_form(p) if p == 0: resu = self * eps else: resu = self.contract(0, eps, 0) for j in range(1, p): resu = resu.self_contract(0, p - j) if p > 1: resu = resu / factorial(p) # Name and LaTeX name of the result: resu.name = format_unop_txt('*', self.name) resu.latex_name = format_unop_latex(r'\star ', self.latex_name) return resu
def exterior_der(self, chart_name=None): r""" Compute the exterior derivative of the differential form. INPUT: - ``chart_name`` -- (default: None): name of the chart used for the computation; if none is provided, the computation is performed in a coordinate basis where the components are known, or computable by a component transformation, privileging the domain's default chart. OUTPUT: - the exterior derivative of ``self``. EXAMPLE: Exterior derivative of a 1-form on a 4-dimensional manifold:: sage: m = Manifold(4, 'M') sage: c_txyz.<t,x,y,z> = m.chart('t x y z', 'coord_txyz') sage: a = OneForm(m, 'A') sage: a[:] = (t*x*y*z, z*y**2, x*z**2, x**2 + y**2) sage: da = a.exterior_der() ; da 2-form 'dA' on the 4-dimensional manifold 'M' sage: da.view() dA = -t*y*z dt/\dx - t*x*z dt/\dy - t*x*y dt/\dz + (-2*y*z + z^2) dx/\dy + (-y^2 + 2*x) dx/\dz + (-2*x*z + 2*y) dy/\dz sage: latex(da) \mathrm{d}A The exterior derivative is nilpotent:: sage: dda = da.exterior_der() ; dda 3-form 'ddA' on the 4-dimensional manifold 'M' sage: dda.view() ddA = 0 sage: dda == 0 True """ from sage.calculus.functional import diff from utilities import format_unop_txt, format_unop_latex if self._exterior_derivative is None: # A new computation is necessary: if chart_name is None: frame_name = self.pick_a_coord_basis() if frame_name is None: raise ValueError("No coordinate basis could be found for " + "the differential form components.") chart_name = frame_name[:-2] chart = self.domain.atlas[chart_name] else: chart = self.domain.atlas[chart_name] frame_name = chart.frame.name if frame_name not in self.components: raise ValueError("Components in the frame " + frame_name + " have not been defined.") n = self.manifold.dim si = self.manifold.sindex sc = self.components[frame_name] dc = CompFullyAntiSym(self.domain.frames[frame_name], self.rank+1) for ind, val in sc._comp.items(): for i in range(n): ind_d = (i+si,) + ind if len(ind_d) == len(set(ind_d)): # all indices are different dc[[ind_d]] += val.function_chart(chart_name).diff(chart.xx[i]) dc._del_zeros() # Name and LaTeX name of the result (rname and rlname): rname = format_unop_txt('d', self.name) rlname = format_unop_latex(r'\mathrm{d}', self.latex_name) # Final result self._exterior_derivative = DiffForm(self.domain, self.rank+1, rname, rlname) self._exterior_derivative.components[frame_name] = dc return self._exterior_derivative
def exterior_der(self, chart_name=None): r""" Compute the exterior derivative of the differential form. INPUT: - ``chart_name`` -- (default: None): name of the chart used for the computation; if none is provided, the computation is performed in a coordinate basis where the components are known, or computable by a component transformation, privileging the manifold's default chart. OUTPUT: - the exterior derivative of ``self``. EXAMPLE: Exterior derivative of a 1-form on a 4-dimensional manifold:: sage: m = Manifold(4, 'M') sage: c_txyz = Chart(m, 't x y z', 'coord_txyz') sage: a = OneForm(m, 'A') sage: a[:] = (t*x*y*z, z*y**2, x*z**2, x**2 + y**2) sage: da = a.exterior_der() ; da 2-form 'dA' on the 4-dimensional manifold 'M' sage: da.show() dA = -t*y*z dt/\dx - t*x*z dt/\dy - t*x*y dt/\dz + (-2*y*z + z^2) dx/\dy + (-y^2 + 2*x) dx/\dz + (-2*x*z + 2*y) dy/\dz sage: latex(da) \mathrm{d}A The exterior derivative is nilpotent:: sage: dda = da.exterior_der() ; dda 3-form 'ddA' on the 4-dimensional manifold 'M' sage: dda.show() ddA = 0 sage: dda == 0 True """ from sage.calculus.functional import diff from utilities import format_unop_txt, format_unop_latex if self._exterior_derivative is None: # A new computation is necessary: if chart_name is None: frame_name = self.pick_a_coord_basis() if frame_name is None: raise ValueError( "No coordinate basis could be found for " + "the differential form components.") chart_name = frame_name[:-2] chart = self.manifold.atlas[chart_name] else: chart = self.manifold.atlas[chart_name] frame_name = chart.frame.name if frame_name not in self.components: raise ValueError("Components in the frame " + frame_name + " have not been defined.") n = self.manifold.dim si = self.manifold.sindex sc = self.components[frame_name] dc = CompFullyAntiSym(self.manifold, self.rank + 1, frame_name) for ind, val in sc._comp.items(): for i in range(n): ind_d = (i + si, ) + ind if len(ind_d) == len( set(ind_d)): # all indices are different dc[[ind_d]] += val.function_chart(chart_name).diff( chart.xx[i]) dc._del_zeros() # Name and LaTeX name of the result (rname and rlname): rname = format_unop_txt('d', self.name) rlname = format_unop_latex(r'\mathrm{d}', self.latex_name) # Final result self._exterior_derivative = DiffForm(self.manifold, self.rank + 1, rname, rlname) self._exterior_derivative.components[frame_name] = dc return self._exterior_derivative