You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
meanas/meanas/fdtd/energy.py

146 lines
4.5 KiB
Python

from typing import Optional, Union
import numpy # type: ignore
from ..fdmath import dx_lists_t, fdfield_t
from ..fdmath.functional import deriv_back
def poynting(e: fdfield_t,
h: fdfield_t,
dxes: Optional[dx_lists_t] = None,
) -> fdfield_t:
"""
Calculate the poynting vector
"""
if dxes is None:
dxes = tuple(tuple(numpy.ones(1) for _ in range(3)) for _ in range(2))
ex = e[0] * dxes[0][0][:, None, None]
ey = e[1] * dxes[0][1][None, :, None]
ez = e[2] * dxes[0][2][None, None, :]
hx = h[0] * dxes[1][0][:, None, None]
hy = h[1] * dxes[1][1][None, :, None]
hz = h[2] * dxes[1][2][None, None, :]
s = numpy.empty_like(e)
s[0] = numpy.roll(ey, -1, axis=0) * hz - numpy.roll(ez, -1, axis=0) * hy
s[1] = numpy.roll(ez, -1, axis=1) * hx - numpy.roll(ex, -1, axis=1) * hz
s[2] = numpy.roll(ex, -1, axis=2) * hy - numpy.roll(ey, -1, axis=2) * hx
return s
def poynting_divergence(s: Optional[fdfield_t] = None,
*,
e: Optional[fdfield_t] = None,
h: Optional[fdfield_t] = None,
dxes: Optional[dx_lists_t] = None,
) -> fdfield_t:
"""
Calculate the divergence of the poynting vector
"""
if s is None:
assert(e is not None)
assert(h is not None)
assert(dxes is not None)
s = poynting(e, h, dxes=dxes)
Dx, Dy, Dz = deriv_back()
ds = Dx(s[0]) + Dy(s[1]) + Dz(s[2])
return ds
def energy_hstep(e0: fdfield_t,
h1: fdfield_t,
e2: fdfield_t,
epsilon: Optional[fdfield_t] = None,
mu: Optional[fdfield_t] = None,
dxes: Optional[dx_lists_t] = None,
) -> fdfield_t:
u = dxmul(e0 * e2, h1 * h1, epsilon, mu, dxes)
return u
def energy_estep(h0: fdfield_t,
e1: fdfield_t,
h2: fdfield_t,
epsilon: Optional[fdfield_t] = None,
mu: Optional[fdfield_t] = None,
dxes: Optional[dx_lists_t] = None,
) -> fdfield_t:
u = dxmul(e1 * e1, h0 * h2, epsilon, mu, dxes)
return u
def delta_energy_h2e(dt: float,
e0: fdfield_t,
h1: fdfield_t,
e2: fdfield_t,
h3: fdfield_t,
epsilon: Optional[fdfield_t] = None,
mu: Optional[fdfield_t] = None,
dxes: Optional[dx_lists_t] = None,
) -> fdfield_t:
"""
This is just from (e2 * e2 + h3 * h1) - (h1 * h1 + e0 * e2)
"""
de = e2 * (e2 - e0) / dt
dh = h1 * (h3 - h1) / dt
du = dxmul(de, dh, epsilon, mu, dxes)
return du
def delta_energy_e2h(dt: float,
h0: fdfield_t,
e1: fdfield_t,
h2: fdfield_t,
e3: fdfield_t,
epsilon: Optional[fdfield_t] = None,
mu: Optional[fdfield_t] = None,
dxes: Optional[dx_lists_t] = None,
) -> fdfield_t:
"""
This is just from (h2 * h2 + e3 * e1) - (e1 * e1 + h0 * h2)
"""
de = e1 * (e3 - e1) / dt
dh = h2 * (h2 - h0) / dt
du = dxmul(de, dh, epsilon, mu, dxes)
return du
def delta_energy_j(j0: fdfield_t,
e1: fdfield_t,
dxes: Optional[dx_lists_t] = None,
) -> fdfield_t:
if dxes is None:
dxes = tuple(tuple(numpy.ones(1) for _ in range(3)) for _ in range(2))
du = ((j0 * e1).sum(axis=0)
* dxes[0][0][:, None, None]
* dxes[0][1][None, :, None]
* dxes[0][2][None, None, :])
return du
def dxmul(ee: fdfield_t,
hh: fdfield_t,
epsilon: Optional[Union[fdfield_t, float]] = None,
mu: Optional[Union[fdfield_t, float]] = None,
dxes: Optional[dx_lists_t] = None
) -> fdfield_t:
if epsilon is None:
epsilon = 1
if mu is None:
mu = 1
if dxes is None:
dxes = tuple(tuple(numpy.ones(1) for _ in range(3)) for _ in range(2))
result = ((ee * epsilon).sum(axis=0)
* dxes[0][0][:, None, None]
* dxes[0][1][None, :, None]
* dxes[0][2][None, None, :]
+ (hh * mu).sum(axis=0)
* dxes[1][0][:, None, None]
* dxes[1][1][None, :, None]
* dxes[1][2][None, None, :])
return result