[waveguide_cyl] enable mu
This commit is contained in:
parent
444ae49a74
commit
f1b1efdb39
1 changed files with 17 additions and 5 deletions
|
|
@ -143,6 +143,7 @@ def cylindrical_operator(
|
||||||
dxes: dx_lists2_t,
|
dxes: dx_lists2_t,
|
||||||
epsilon: vfdslice,
|
epsilon: vfdslice,
|
||||||
rmin: float,
|
rmin: float,
|
||||||
|
mu: vfdslice | None = None,
|
||||||
) -> sparse.sparray:
|
) -> sparse.sparray:
|
||||||
r"""
|
r"""
|
||||||
Cylindrical coordinate waveguide operator of the form
|
Cylindrical coordinate waveguide operator of the form
|
||||||
|
|
@ -176,10 +177,13 @@ def cylindrical_operator(
|
||||||
dxes: Grid parameters `[dx_e, dx_h]` as described in `meanas.fdmath.types` (2D)
|
dxes: Grid parameters `[dx_e, dx_h]` as described in `meanas.fdmath.types` (2D)
|
||||||
epsilon: Vectorized dielectric constant grid
|
epsilon: Vectorized dielectric constant grid
|
||||||
rmin: Radius at the left edge of the simulation domain (at minimum 'x')
|
rmin: Radius at the left edge of the simulation domain (at minimum 'x')
|
||||||
|
mu: Vectorized magnetic permeability grid (default 1 everywhere)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Sparse matrix representation of the operator
|
Sparse matrix representation of the operator
|
||||||
"""
|
"""
|
||||||
|
if mu is None:
|
||||||
|
mu = numpy.ones_like(epsilon)
|
||||||
|
|
||||||
Dfx, Dfy = deriv_forward(dxes[0])
|
Dfx, Dfy = deriv_forward(dxes[0])
|
||||||
Dbx, Dby = deriv_back(dxes[1])
|
Dbx, Dby = deriv_back(dxes[1])
|
||||||
|
|
@ -191,12 +195,17 @@ def cylindrical_operator(
|
||||||
eps_y = sparse.diags_array(eps_parts[1])
|
eps_y = sparse.diags_array(eps_parts[1])
|
||||||
eps_z_inv = sparse.diags_array(1 / eps_parts[2])
|
eps_z_inv = sparse.diags_array(1 / eps_parts[2])
|
||||||
|
|
||||||
|
mu_parts = numpy.split(mu, 3)
|
||||||
|
mu_y = sparse.diags_array(mu_parts[1])
|
||||||
|
mu_x = sparse.diags_array(mu_parts[0])
|
||||||
|
mu_z_inv = sparse.diags_array(1 / mu_parts[2])
|
||||||
|
|
||||||
omega2 = omega * omega
|
omega2 = omega * omega
|
||||||
diag = sparse.block_diag
|
diag = sparse.block_diag
|
||||||
|
|
||||||
sq0 = omega2 * diag((Tb @ Tb @ eps_x,
|
sq0 = omega2 * diag((Tb @ Tb @ mu_y @ eps_x,
|
||||||
Ta @ Ta @ eps_y))
|
Ta @ Ta @ mu_x @ eps_y))
|
||||||
lin0 = sparse.vstack((-Tb @ Dby, Ta @ Dbx)) @ Tb @ sparse.hstack((-Dfy, Dfx))
|
lin0 = sparse.vstack((-Tb @ mu_y @ Dby, Ta @ mu_x @ Dbx)) @ Tb @ mu_z_inv @ sparse.hstack((-Dfy, Dfx))
|
||||||
lin1 = sparse.vstack((Dfx, Dfy)) @ Ta @ eps_z_inv @ sparse.hstack((Dbx @ Tb @ eps_x,
|
lin1 = sparse.vstack((Dfx, Dfy)) @ Ta @ eps_z_inv @ sparse.hstack((Dbx @ Tb @ eps_x,
|
||||||
Dby @ Ta @ eps_y))
|
Dby @ Ta @ eps_y))
|
||||||
op = sq0 + lin0 + lin1
|
op = sq0 + lin0 + lin1
|
||||||
|
|
@ -209,6 +218,7 @@ def solve_modes(
|
||||||
dxes: dx_lists2_t,
|
dxes: dx_lists2_t,
|
||||||
epsilon: vfdslice,
|
epsilon: vfdslice,
|
||||||
rmin: float,
|
rmin: float,
|
||||||
|
mu: vfdslice | None = None,
|
||||||
mode_margin: int = 2,
|
mode_margin: int = 2,
|
||||||
) -> tuple[NDArray[numpy.complex128], NDArray[numpy.complex128]]:
|
) -> tuple[NDArray[numpy.complex128], NDArray[numpy.complex128]]:
|
||||||
"""
|
"""
|
||||||
|
|
@ -223,6 +233,7 @@ def solve_modes(
|
||||||
epsilon: Dielectric constant
|
epsilon: Dielectric constant
|
||||||
rmin: Radius of curvature for the simulation. This should be the minimum value of
|
rmin: Radius of curvature for the simulation. This should be the minimum value of
|
||||||
r within the simulation domain.
|
r within the simulation domain.
|
||||||
|
mu: Magnetic permeability (default 1 everywhere)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
e_xys: NDArray of vfdfield_t specifying fields. First dimension is mode number.
|
e_xys: NDArray of vfdfield_t specifying fields. First dimension is mode number.
|
||||||
|
|
@ -233,8 +244,9 @@ def solve_modes(
|
||||||
# Solve for the largest-magnitude eigenvalue of the real operator
|
# Solve for the largest-magnitude eigenvalue of the real operator
|
||||||
#
|
#
|
||||||
dxes_real = [[numpy.real(dx) for dx in dxi] for dxi in dxes]
|
dxes_real = [[numpy.real(dx) for dx in dxi] for dxi in dxes]
|
||||||
|
mu_real = None if mu is None else numpy.real(mu)
|
||||||
|
|
||||||
A_r = cylindrical_operator(numpy.real(omega), dxes_real, numpy.real(epsilon), rmin=rmin)
|
A_r = cylindrical_operator(numpy.real(omega), dxes_real, numpy.real(epsilon), rmin=rmin, mu=mu_real)
|
||||||
eigvals, eigvecs = signed_eigensolve(A_r, max(mode_numbers) + mode_margin)
|
eigvals, eigvecs = signed_eigensolve(A_r, max(mode_numbers) + mode_margin)
|
||||||
keep_inds = -(numpy.array(mode_numbers) + 1)
|
keep_inds = -(numpy.array(mode_numbers) + 1)
|
||||||
e_xys = eigvecs[:, keep_inds].T
|
e_xys = eigvecs[:, keep_inds].T
|
||||||
|
|
@ -244,7 +256,7 @@ def solve_modes(
|
||||||
# Now solve for the eigenvector of the full operator, using the real operator's
|
# Now solve for the eigenvector of the full operator, using the real operator's
|
||||||
# eigenvector as an initial guess for Rayleigh quotient iteration.
|
# eigenvector as an initial guess for Rayleigh quotient iteration.
|
||||||
#
|
#
|
||||||
A = cylindrical_operator(omega, dxes, epsilon, rmin=rmin)
|
A = cylindrical_operator(omega, dxes, epsilon, rmin=rmin, mu=mu)
|
||||||
for nn in range(len(mode_numbers)):
|
for nn in range(len(mode_numbers)):
|
||||||
eigvals[nn], e_xys[nn, :] = rayleigh_quotient_iteration(A, e_xys[nn, :])
|
eigvals[nn], e_xys[nn, :] = rayleigh_quotient_iteration(A, e_xys[nn, :])
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue