from typing import Optional
import numpy as np
from interpn import MultilinearRectilinear
from numpy.typing import NDArray
from scipy.constants import mu_0
from scipy.special import ellipe, ellipk
import cfsem
def _self_inductance_filamentized(
r, z, dr, dz, nt, nr, nz, mask: Optional[tuple[NDArray, NDArray, NDArray]] = None
) -> float:
fs = cfsem.filament_coil(r, z, dr, dz, nt, nr, nz) if mask is not None:
interp = MultilinearRectilinear.new([mask[0], mask[1]], mask[2].flatten())
fs = np.array(
[f for f in fs if interp.eval([np.array([f[0]]), np.array([f[1]])]) > 0.0]
)
fs[:, 2] *= nt / np.sum(fs[:, 2])
nfil = fs.shape[0]
M = np.zeros((nfil, nfil))
for i in range(nfil):
for j in range(nfil):
if i != j:
M[i, j] = _mutual_inductance_of_circular_filaments(
fs[i, :], fs[j, :]
) else:
major_radius_filament = fs[i, :][0] minor_radius_filament = (
(dr / nr) / 2
) num_turns = fs[i, :][2] L_f = num_turns**2 * cfsem.self_inductance_circular_ring_wien(
major_radius_filament, minor_radius_filament
) M[i, j] = (
L_f )
L = np.sum(np.sum(M))
return L
def _flux_density_circular_filament_numerical(
I: float, a: float, r: float, z: float, n: int = 100
) -> tuple[float, float]:
mu_0_over_4pi = 1e-7 a0 = mu_0_over_4pi * I * a
phis = np.linspace(0.0 + 1e-8, 2.0 * np.pi - 1e-8, n)
a1 = (a**2 + r**2 + z**2 - 2.0 * r * a * np.sin(phis)) ** -1.5
Brs = a0 * z * np.sin(phis) * a1
Br = np.trapezoid(x=phis, y=Brs)
Bzs = a0 * (a - r * np.sin(phis)) * a1
Bz = np.trapezoid(x=phis, y=Bzs)
return Br, Bz
def _mutual_inductance_of_circular_filaments(rzn1: NDArray, rzn2: NDArray) -> float:
r1, z1, n1 = rzn1
r2, z2, n2 = rzn2
k2 = 4 * r1 * r2 / ((r1 + r2) ** 2 + (z1 - z2) ** 2)
amp = 2 * mu_0 * r1 * r2 / np.sqrt((r1 + r2) ** 2 + (z1 - z2) ** 2)
M0 = n1 * n2 * amp * ((2 - k2) * ellipk(k2) - 2 * ellipe(k2)) / k2
return M0
def _mutual_inductance_of_cylindrical_coils(f1: NDArray, f2: NDArray) -> float:
M = 0.0
for i in range(f1.shape[0]):
for j in range(f2.shape[0]):
M += _mutual_inductance_of_circular_filaments(f1[i, :], f2[j, :])
return M
def _filament_coil_comprehension(
r: float, z: float, w: float, h: float, nt: float, nr: int, nz: int
) -> NDArray:
rs = np.linspace(r - w * (nr - 1) / nr / 2, r + w * (nr - 1) / nr / 2, nr)
zs = np.linspace(z - h * (nz - 1) / nz / 2, z + h * (nz - 1) / nz / 2, nz)
rz = [(rr, zz) for rr in rs for zz in zs]
R = [x[0] for x in rz]
Z = [x[1] for x in rz]
N = np.full_like(R, float(nt) / (nr * nz))
filaments = np.dstack([R, Z, N]).reshape(nr * nz, 3)
return filaments
def _filament_loop(
r: float, z: float, ndiscr: int
) -> tuple[tuple[NDArray, NDArray, NDArray], tuple[NDArray, NDArray, NDArray]]:
phi = np.linspace(0.0, 2.0 * np.pi, ndiscr)
x = r * np.cos(phi)
y = r * np.sin(phi)
z = z * np.ones_like(x)
dx = np.diff(x)
dy = np.diff(y)
dz = np.diff(z)
return ((x, y, z), (dx, dy, dz))