Running Sage Math and sagemanifolds with jupyter notebooks tip: First, I've found that compiling from the github source the development Sage Math version (see my notes on this under the "Computers" section of my wordpress blog) works with sagemanifolds and either installing sagemanifolds into the binary that you unpack out (the click, download, double click), "breaks" Sage and so that it doesn't run. Also, following the Sage Math instructions on their website for building from the source didn't work for me (!!!???).
As a tip on how to run this jupyter notebook and have sagemanifolds available, you'd want to be in the working directory you desire (e.g. Propulsion/EM
). But yet your Sage Math build is somewhere else (e.g. /home/topolo/Public/sage
). Do this out of the working directory you're currently working out of:
/home/topolo/Public/sage/sage -n jupyter
For the rationale, or the math, and how the math corresponds directly to the Sage Math code here, you're going to want to look at Gravity_Notes_grande.pdf in my Gravite repository, and in there, the $\mathbb{R}^3$ section, because I define the charts and atlases for Euclidean space $\mathbb{R}^3$ as a smooth manifold.
%display latex
M = Manifold(4,'M',r'M')
cart_ch = M.chart('t x y z')
U = M.open_subset('U',coord_def={cart_ch: (cart_ch[1]<0, cart_ch[2]!=0)})
cart_ch_U = cart_ch.restrict(U)
sph_ch = U.chart(r't:(-oo,oo):t rh:(0,+oo):\rho th:(0,pi):\theta ph:(0,2*pi):\phi')
t, rh,th,ph = [sph_ch[i[0]] for i in M.index_generator(1)]
transit_sph_to_cart = sph_ch.transition_map(cart_ch_U,
[t,rh*sin(th)*cos(ph),rh*sin(th)*sin(ph),rh*cos(th)])
Sphnorm = sqrt(sum([cart_ch_U[i]**2 for i in range(1,4)]))
transit_sph_to_cart.set_inverse( cart_ch[0], Sphnorm,
atan2(sqrt( sum([ cart_ch_U[i]**2 for i in range(1,3)])),cart_ch_U[3]),
atan2(cart_ch_U[2],cart_ch_U[1]))
cyl_ch = U.chart(r't:(-oo,oo):t r:(0,+oo) phi:(0,2*pi):\phi z:(-oo,oo):z')
t, r,phi,z = [cyl_ch[i[0]] for i in M.index_generator(1)]
transit_cyl_to_cart = cyl_ch.transition_map(cart_ch_U, [t,r*cos(phi),r*sin(phi),z])
transit_cyl_to_cart.set_inverse(cart_ch_U[0], sqrt(cart_ch_U[1]**2+cart_ch_U[2]**2),
atan2( cart_ch_U[2],cart_ch_U[1]), cart_ch_U[3])
Note the mostly positive (-+++) convention I use for the Minkowski metric.
g = M.lorentzian_metric('g')
g[0,0] = -1
for i in range(1,4): g[i,i] = 1
def make_E(ch):
"""
make_E = make_E(ch)
make_E creates a time-INDEPENDENT electric field as a 1-form
INPUT/PARAMETER
ch = sagemanifold chart
"""
Ecomplst = []
for i in range(1,4):
Earglst = ['E'+str(i),] + list(ch[1:])
Ecomplst.append( function(Earglst[0])(*Earglst[1:]) )
Ecomplst = [0,]+Ecomplst
E = ch.domain().diff_form(1)
E[ch.frame(),:,ch] = Ecomplst
return E
def make_Et(ch):
"""
make_Et = make_Et(ch)
make_Et creates a time-DEPENDENT electric field as a 1-form
INPUT/PARAMETER
ch = sagemanifold chart
"""
Ecomplst = []
for i in range(1,4):
Earglst = ['E'+str(i),] + list(ch[:])
Ecomplst.append( function(Earglst[0])(*Earglst[1:]) )
Ecomplst = [0,]+Ecomplst
E = ch.domain().diff_form(1)
E[ch.frame(),:,ch] = Ecomplst
return E
Examples of using make_E
, make_Et
and displaying the results
print make_E(cart_ch).display()
make_Et(sph_ch).display(sph_ch.frame(),sph_ch)
E1(x, y, z) dx + E2(x, y, z) dy + E3(x, y, z) dz
Programming note: make_B
and make_Bt
def make_B(ch):
"""
make_B = make_B(ch)
make_B creates a time-INDEPENDENT magnetic field as a 2-form
INPUT/PARAMETER
ch = sagemanifold chart
"""
B = ch.domain().diff_form(2)
farglst = list(ch[1:]) # function argument list, e.g. (x,y,z)
B[ch.frame(),1,2,ch] = function('B_12')(*farglst)
B[ch.frame(),2,3,ch] = function('B_23')(*farglst)
B[ch.frame(),3,1,ch] = function('B_31')(*farglst)
return B
def make_Bt(ch):
"""
make_Bt = make_Bt(ch)
make_Bt creates a time-DEPENDENT electric field as a 2-form
INPUT/PARAMETER
ch = sagemanifold chart
"""
B = ch.domain().diff_form(2)
farglst = list(ch[:]) # function argument list, e.g. (x,y,z)
B[ch.frame(),1,2,ch] = function('B_12')(*farglst)
B[ch.frame(),2,3,ch] = function('B_23')(*farglst)
B[ch.frame(),3,1,ch] = function('B_31')(*farglst)
return B
print make_Bt(cart_ch).display()
make_B(cyl_ch).display(cyl_ch.frame(),cyl_ch)
B_12(t, x, y, z) dx/\dy - B_31(t, x, y, z) dx/\dz + B_23(t, x, y, z) dy/\dz
Notice that the orientation is correct (with the right hand rule).
EM_F = make_Bt(cart_ch) + make_Et(cart_ch).wedge(cart_ch.coframe()[0] )
EM_F.display()
EM_F[:]
EM_F.exterior_der()[:]
And so
$ dF = \left[\left[\left[0, 0, 0, 0\right], \left[0, 0, \frac{\partial\,B_{12}}{\partial {t}} - \frac{\partial\,E_{1}}{\partial y} + \frac{\partial\,E_{2}}{\partial x}, -\frac{\partial\,B_{31}}{\partial {t}} - \frac{\partial\,E_{1}}{\partial z} + \frac{\partial\,E_{3}}{\partial x}\right], \left[0, -\frac{\partial\,B_{12}}{\partial {t}} + \frac{\partial\,E_{1}}{\partial y} - \frac{\partial\,E_{2}}{\partial x}, 0, \frac{\partial\,B_{23}}{\partial {t}} - \frac{\partial\,E_{2}}{\partial z} + \frac{\partial\,E_{3}}{\partial y}\right], \left[0, \frac{\partial\,B_{31}}{\partial {t}} + \frac{\partial\,E_{1}}{\partial z} - \frac{\partial\,E_{3}}{\partial x}, -\frac{\partial\,B_{23}}{\partial {t}} + \frac{\partial\,E_{2}}{\partial z} - \frac{\partial\,E_{3}}{\partial y}, 0\right]\right], \left[\left[0, 0, -\frac{\partial\,B_{12}}{\partial {t}} + \frac{\partial\,E_{1}}{\partial y} - \frac{\partial\,E_{2}}{\partial x}, \frac{\partial\,B_{31}}{\partial {t}} + \frac{\partial\,E_{1}}{\partial z} - \frac{\partial\,E_{3}}{\partial x}\right], \left[0, 0, 0, 0\right], \left[\frac{\partial\,B_{12}}{\partial {t}} - \frac{\partial\,E_{1}}{\partial y} + \frac{\partial\,E_{2}}{\partial x}, 0, 0, \frac{\partial\,B_{12}}{\partial z} + \frac{\partial\,B_{23}}{\partial x} + \frac{\partial\,B_{31}}{\partial y}\right], \left[-\frac{\partial\,B_{31}}{\partial {t}} - \frac{\partial\,E_{1}}{\partial z} + \frac{\partial\,E_{3}}{\partial x}, 0, -\frac{\partial\,B_{12}}{\partial z} - \frac{\partial\,B_{23}}{\partial x} - \frac{\partial\,B_{31}}{\partial y}, 0\right]\right], \left[\left[0, \frac{\partial\,B_{12}}{\partial {t}} - \frac{\partial\,E_{1}}{\partial y} + \frac{\partial\,E_{2}}{\partial x}, 0, -\frac{\partial\,B_{23}}{\partial {t}} + \frac{\partial\,E_{2}}{\partial z} - \frac{\partial\,E_{3}}{\partial y}\right], \left[-\frac{\partial\,B_{12}}{\partial {t}} + \frac{\partial\,E_{1}}{\partial y} - \frac{\partial\,E_{2}}{\partial x}, 0, 0, -\frac{\partial\,B_{12}}{\partial z} - \frac{\partial\,B_{23}}{\partial x} - \frac{\partial\,B_{31}}{\partial y}\right], \left[0, 0, 0, 0\right], \left[\frac{\partial\,B_{23}}{\partial {t}} - \frac{\partial\,E_{2}}{\partial z} + \frac{\partial\,E_{3}}{\partial y}, \frac{\partial\,B_{12}}{\partial z} + \frac{\partial\,B_{23}}{\partial x} + \frac{\partial\,B_{31}}{\partial y}, 0, 0\right]\right], \left[\left[0, -\frac{\partial\,B_{31}}{\partial {t}} - \frac{\partial\,E_{1}}{\partial z} + \frac{\partial\,E_{3}}{\partial x}, \frac{\partial\,B_{23}}{\partial {t}} - \frac{\partial\,E_{2}}{\partial z} + \frac{\partial\,E_{3}}{\partial y}, 0\right], \left[\frac{\partial\,B_{31}}{\partial {t}} + \frac{\partial\,E_{1}}{\partial z} - \frac{\partial\,E_{3}}{\partial x}, 0, \frac{\partial\,B_{12}}{\partial z} + \frac{\partial\,B_{23}}{\partial x} + \frac{\partial\,B_{31}}{\partial y}, 0\right], \left[-\frac{\partial\,B_{23}}{\partial {t}} + \frac{\partial\,E_{2}}{\partial z} - \frac{\partial\,E_{3}}{\partial y}, -\frac{\partial\,B_{12}}{\partial z} - \frac{\partial\,B_{23}}{\partial x} - \frac{\partial\,B_{31}}{\partial y}, 0, 0\right], \left[0, 0, 0, 0\right]\right]\right] = 0 $
EM_F.hodge_dual(g)[:]
As a reminder, the Minkowski metric is a Lorentzian metric (not a Riemannian metric, which, in sagemanifolds
, translates into using the lorentzian_metric module/function, not the riemannian_metric module/function) and is given by $g$:
g[:]
$d*F$ (for $d*F = 4 \pi * J$)
EM_F.hodge_dual(g).exterior_der()[:]
As a reminder, if you wanted the LaTeX code, use the latex
function in Sage Math like such:
latex( EM_F.hodge_dual(g).exterior_der()[:] ); # delete the semi-colon ; and you can get the LaTeX code-I suppress it
And so
$d*F = \left[\left[\left[0, 0, 0, 0\right], \left[0, 0, i \, \frac{\partial\,B_{23}}{\partial y} - i \, \frac{\partial\,B_{31}}{\partial x} + i \, \frac{\partial\,E_{3}}{\partial {t}}, -i \, \frac{\partial\,B_{12}}{\partial x} + i \, \frac{\partial\,B_{23}}{\partial z} - i \, \frac{\partial\,E_{2}}{\partial {t}}\right], \left[0, -i \, \frac{\partial\,B_{23}}{\partial y} + i \, \frac{\partial\,B_{31}}{\partial x} - i \, \frac{\partial\,E_{3}}{\partial {t}}, 0, -i \, \frac{\partial\,B_{12}}{\partial y} + i \, \frac{\partial\,B_{31}}{\partial z} + i \, \frac{\partial\,E_{1}}{\partial {t}}\right], \left[0, i \, \frac{\partial\,B_{12}}{\partial x} - i \, \frac{\partial\,B_{23}}{\partial z} + i \, \frac{\partial\,E_{2}}{\partial {t}}, i \, \frac{\partial\,B_{12}}{\partial y} - i \, \frac{\partial\,B_{31}}{\partial z} - i \, \frac{\partial\,E_{1}}{\partial {t}}, 0\right]\right], \left[\left[0, 0, -i \, \frac{\partial\,B_{23}}{\partial y} + i \, \frac{\partial\,B_{31}}{\partial x} - i \, \frac{\partial\,E_{3}}{\partial {t}}, i \, \frac{\partial\,B_{12}}{\partial x} - i \, \frac{\partial\,B_{23}}{\partial z} + i \, \frac{\partial\,E_{2}}{\partial {t}}\right], \left[0, 0, 0, 0\right], \left[i \, \frac{\partial\,B_{23}}{\partial y} - i \, \frac{\partial\,B_{31}}{\partial x} + i \, \frac{\partial\,E_{3}}{\partial {t}}, 0, 0, i \, \frac{\partial\,E_{1}}{\partial x} + i \, \frac{\partial\,E_{2}}{\partial y} + i \, \frac{\partial\,E_{3}}{\partial z}\right], \left[-i \, \frac{\partial\,B_{12}}{\partial x} + i \, \frac{\partial\,B_{23}}{\partial z} - i \, \frac{\partial\,E_{2}}{\partial {t}}, 0, -i \, \frac{\partial\,E_{1}}{\partial x} - i \, \frac{\partial\,E_{2}}{\partial y} - i \, \frac{\partial\,E_{3}}{\partial z}, 0\right]\right], \left[\left[0, i \, \frac{\partial\,B_{23}}{\partial y} - i \, \frac{\partial\,B_{31}}{\partial x} + i \, \frac{\partial\,E_{3}}{\partial {t}}, 0, i \, \frac{\partial\,B_{12}}{\partial y} - i \, \frac{\partial\,B_{31}}{\partial z} - i \, \frac{\partial\,E_{1}}{\partial {t}}\right], \left[-i \, \frac{\partial\,B_{23}}{\partial y} + i \, \frac{\partial\,B_{31}}{\partial x} - i \, \frac{\partial\,E_{3}}{\partial {t}}, 0, 0, -i \, \frac{\partial\,E_{1}}{\partial x} - i \, \frac{\partial\,E_{2}}{\partial y} - i \, \frac{\partial\,E_{3}}{\partial z}\right], \left[0, 0, 0, 0\right], \left[-i \, \frac{\partial\,B_{12}}{\partial y} + i \, \frac{\partial\,B_{31}}{\partial z} + i \, \frac{\partial\,E_{1}}{\partial {t}}, i \, \frac{\partial\,E_{1}}{\partial x} + i \, \frac{\partial\,E_{2}}{\partial y} + i \, \frac{\partial\,E_{3}}{\partial z}, 0, 0\right]\right], \left[\left[0, -i \, \frac{\partial\,B_{12}}{\partial x} + i \, \frac{\partial\,B_{23}}{\partial z} - i \, \frac{\partial\,E_{2}}{\partial {t}}, -i \, \frac{\partial\,B_{12}}{\partial y} + i \, \frac{\partial\,B_{31}}{\partial z} + i \, \frac{\partial\,E_{1}}{\partial {t}}, 0\right], \left[i \, \frac{\partial\,B_{12}}{\partial x} - i \, \frac{\partial\,B_{23}}{\partial z} + i \, \frac{\partial\,E_{2}}{\partial {t}}, 0, i \, \frac{\partial\,E_{1}}{\partial x} + i \, \frac{\partial\,E_{2}}{\partial y} + i \, \frac{\partial\,E_{3}}{\partial z}, 0\right], \left[i \, \frac{\partial\,B_{12}}{\partial y} - i \, \frac{\partial\,B_{31}}{\partial z} - i \, \frac{\partial\,E_{1}}{\partial {t}}, -i \, \frac{\partial\,E_{1}}{\partial x} - i \, \frac{\partial\,E_{2}}{\partial y} - i \, \frac{\partial\,E_{3}}{\partial z}, 0, 0\right], \left[0, 0, 0, 0\right]\right]\right]$
EM_F.hodge_dual(g).exterior_der().hodge_dual(g)[:]
latex(EM_F.hodge_dual(g).exterior_der().hodge_dual(g)[:]);
# delete the semi-colon ; and you can get the LaTeX code-I suppress it
\left[\frac{\partial\,E_{1}}{\partial x} + \frac{\partial\,E_{2}}{\partial y} + \frac{\partial\,E_{3}}{\partial z}, -\frac{\partial\,B_{12}}{\partial y} + \frac{\partial\,B_{31}}{\partial z} + \frac{\partial\,E_{1}}{\partial {t}}, \frac{\partial\,B_{12}}{\partial x} - \frac{\partial\,B_{23}}{\partial z} + \frac{\partial\,E_{2}}{\partial {t}}, \frac{\partial\,B_{23}}{\partial y} - \frac{\partial\,B_{31}}{\partial x} + \frac{\partial\,E_{3}}{\partial {t}}\right]
And so
$*d*F = \left[\frac{\partial\,E_{1}}{\partial x} + \frac{\partial\,E_{2}}{\partial y} + \frac{\partial\,E_{3}}{\partial z}, -\frac{\partial\,B_{12}}{\partial y} + \frac{\partial\,B_{31}}{\partial z} + \frac{\partial\,E_{1}}{\partial {t}}, \frac{\partial\,B_{12}}{\partial x} - \frac{\partial\,B_{23}}{\partial z} + \frac{\partial\,E_{2}}{\partial {t}}, \frac{\partial\,B_{23}}{\partial y} - \frac{\partial\,B_{31}}{\partial x} + \frac{\partial\,E_{3}}{\partial {t}}\right]$
def make_J(ch):
"""
make_J = make_J(ch)
make_J creates a time-INDEPENDENT current as a 1-form
INPUT/PARAMETER
ch = sagemanifold chart
"""
Jcomplst = []
for i in range(1,4):
Jarglst = ['j'+str(i),] + list(ch[1:])
Jcomplst.append( function(Jarglst[0])(*Jarglst[1:]) )
Jcomplst = [-function('rho')(*list(ch[1:])),] +Jcomplst
J = ch.domain().diff_form(1)
J[ch.frame(),:,ch] = Jcomplst
return J
def make_Jt(ch):
"""
make_Jt = make_Jt(ch)
make_Jt creates a time-DEPENDENT current as a 1-form
INPUT/PARAMETER
ch = sagemanifold chart
"""
Jcomplst = []
for i in range(1,4):
Jarglst = ['j'+str(i),] + list(ch[:])
Jcomplst.append( function(Jarglst[0])(*Jarglst[1:]) )
Jcomplst = [-function('rho')(*list(ch[:])),]+Jcomplst
J = ch.domain().diff_form(1)
J[ch.frame(),:,ch] = Jcomplst
return J
print make_Jt(cart_ch).display() # these are examples of displaying the 4-current as 1-form in
# Cartesian and cylindrical coordinates
make_Jt(cyl_ch).display(cyl_ch.frame(),cyl_ch)
-rho(t, x, y, z) dt + j1(t, x, y, z) dx + j2(t, x, y, z) dy + j3(t, x, y, z) dz
make_Jt(cart_ch).hodge_dual(g).hodge_dual(g).display()
So here, I had successfully shown that $*d*F = **J$ or $*d*F = 4\pi ** J$ (in cgs units), thus recovering Gauss's law and Ampere's law.
latex( make_Jt(cart_ch).hodge_dual(g).hodge_dual(g)[:]);
# delete the semi-colon ; and you can get the LaTeX code-I suppress it
$\boxed{ \left[\frac{\partial\,E_{1}}{\partial x} + \frac{\partial\,E_{2}}{\partial y} + \frac{\partial\,E_{3}}{\partial z}, -\frac{\partial\,B_{12}}{\partial y} + \frac{\partial\,B_{31}}{\partial z} + \frac{\partial\,E_{1}}{\partial {t}}, \frac{\partial\,B_{12}}{\partial x} - \frac{\partial\,B_{23}}{\partial z} + \frac{\partial\,E_{2}}{\partial {t}}, \frac{\partial\,B_{23}}{\partial y} - \frac{\partial\,B_{31}}{\partial x} + \frac{\partial\,E_{3}}{\partial {t}}\right] = \left[\rho\left({t}, x, y, z\right), -j_{1}\left({t}, x, y, z\right), -j_{2}\left({t}, x, y, z\right), -j_{3}\left({t}, x, y, z\right)\right] }$
Current conservation is easily calculated, $*d*J=0$:
make_Jt(cart_ch).hodge_dual(g).exterior_der().hodge_dual(g).display(cart_ch)
def make_beta(ch):
"""
make_beta = make_beta(ch)
make_beta creates a time-INDEPENDENT velocity field
INPUT/PARAMETER
ch = sagemanifold chart
"""
betacomplst = []
for i in range(1,4):
betaarglst = ['beta'+str(i),] + list(ch[1:])
betacomplst.append( function(betaarglst[0])(*betaarglst[1:]) )
betacomplst = [1,]+betacomplst
beta = ch.domain().vector_field()
beta[ch.frame(),:,ch] = betacomplst
return beta
def make_betat(ch):
"""
make_betat = make_betat(ch)
make_betat creates a time-DEPENDENT velocity field
INPUT/PARAMETER
ch = sagemanifold chart
"""
betacomplst = []
for i in range(1,4):
betaarglst = ['beta'+str(i),] + list(ch[:])
betacomplst.append( function(betaarglst[0])(*betaarglst[1:]) )
betacomplst = [1,]+betacomplst
beta = ch.domain().vector_field()
beta[ch.frame(),:,ch] = betacomplst
return beta
make_beta(cart_ch).display()
For interior products, you're going to have to dig into how sagemanifolds implements Tensor products, tensor contractions, and the use of index notation, as sagemanifolds doesn't have a "stand-alone" interior product function. From my EuclideanManifold.py implementation in sagemanifolds, look at my curl function (def curl
) as a template for implementing interior products.
betaeg = make_betat(cart_ch)
Beg = make_Bt(cart_ch)
(betaeg['^i']*Beg['_ij']).display()
So we now have a prescription on how to implement both the interior product and the curl of 2 "vectors" -
if you want this:
$-i_{\mathbf{\beta}} B$ which is the differential form version of $\mathbf{\beta} \times B$ (curl), then do this in sagemanifolds:
-betaeg['^i']*Beg['_ij']
q = var('q',domain="real") # define a single charge variable in Sage Math
LorentzForce1form = make_Et(cart_ch) - make_beta(cart_ch)['^i']*make_Bt(cart_ch)['_ij']
You can multiply this differential 1-form with Sage Math variables.
LorentzForce1form = q * LorentzForce1form
The 1-form version of the Lorentz Force $F$ is given by the following, and keep in mind that we integrate 1-forms, we don't integrate vectors (because it goes back to how we transport vectors along a curve, and 1-forms either abscond, circumvent, this problem or is the most natural way to do integration on manifolds):
LorentzForce1form.display()
And so
$f = \left( q B_{12}\left({t}, x, y, z\right) \beta_{2}\left(x, y, z\right) - q B_{31}\left({t}, x, y, z\right) \beta_{3}\left(x, y, z\right) + q E_{1}\left({t}, x, y, z\right) \right) \mathrm{d} x + \left( -q B_{12}\left({t}, x, y, z\right) \beta_{1}\left(x, y, z\right) + q B_{23}\left({t}, x, y, z\right) \beta_{3}\left(x, y, z\right) + q E_{2}\left({t}, x, y, z\right) \right) \mathrm{d} y + \left( q B_{31}\left({t}, x, y, z\right) \beta_{1}\left(x, y, z\right) - q B_{23}\left({t}, x, y, z\right) \beta_{2}\left(x, y, z\right) + q E_{3}\left({t}, x, y, z\right) \right) \mathrm{d} z$
$F \wedge * F$
FwedgestarF = EM_F.wedge(EM_F.hodge_dual(g))
FwedgestarF.display()
$E\cdot B$
Eteg = make_Et(cart_ch)
Bteg = make_Bt(cart_ch)
EdotB = Eteg.wedge( Bteg)
EdotB.display()
Try $E \wedge *B$
(Eteg.wedge( Bteg.hodge_dual(g))).display()