Electromagnetism

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.

In [1]:
%display latex
In [2]:
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.

In [3]:
g = M.lorentzian_metric('g')
g[0,0] = -1 
for i in range(1,4): g[i,i] = 1

Electric Field

In [4]:
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

In [5]:
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
Out[5]:

Magnetic Field

Programming note: make_B and make_Bt

In [6]:
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
In [7]:
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
Out[7]:

Notice that the orientation is correct (with the right hand rule).

Electromagnetic field 2-form

In [8]:
EM_F = make_Bt(cart_ch) + make_Et(cart_ch).wedge(cart_ch.coframe()[0] )
EM_F.display()
Out[8]:
In [9]:
EM_F[:]
Out[9]:
In [10]:
EM_F.exterior_der()[:]
Out[10]:

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 $

In [11]:
EM_F.hodge_dual(g)[:]
Out[11]:

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$:

In [12]:
g[:]
Out[12]:

$d*F$ (for $d*F = 4 \pi * J$)

In [13]:
EM_F.hodge_dual(g).exterior_der()[:]
Out[13]:

As a reminder, if you wanted the LaTeX code, use the latex function in Sage Math like such:

In [78]:
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]$

In [14]:
EM_F.hodge_dual(g).exterior_der().hodge_dual(g)[:] 
Out[14]:
In [81]:
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
Out[81]:
\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]$

Current 1-form, Current conservation, and the other side (Right-Hand Side (RHS)) of $d*F$

In [15]:
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
    
In [16]:
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
Out[16]:
In [17]:
make_Jt(cart_ch).hodge_dual(g).hodge_dual(g).display()
Out[17]:

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.

In [115]:
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$:

In [18]:
make_Jt(cart_ch).hodge_dual(g).exterior_der().hodge_dual(g).display(cart_ch)
Out[18]:

Lorentz Force

In [19]:
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
In [20]:
make_beta(cart_ch).display()
Out[20]:

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.

In [21]:
betaeg = make_betat(cart_ch)
Beg = make_Bt(cart_ch)
(betaeg['^i']*Beg['_ij']).display()
Out[21]:

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']

In [22]:
q = var('q',domain="real") # define a single charge variable in Sage Math
In [23]:
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.

In [24]:
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):

In [25]:
LorentzForce1form.display() 
Out[25]:

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$

More "combinations": $F \wedge *F$

$F \wedge * F$

In [26]:
FwedgestarF = EM_F.wedge(EM_F.hodge_dual(g))
In [27]:
FwedgestarF.display()
Out[27]:

$E\cdot B$

In [28]:
Eteg = make_Et(cart_ch)
Bteg = make_Bt(cart_ch)
EdotB = Eteg.wedge( Bteg)
EdotB.display()
Out[28]:

Poynting Vector

Try $E \wedge *B$

In [29]:
(Eteg.wedge( Bteg.hodge_dual(g))).display()
Out[29]:
In [ ]: