Skip to content

Vector Potential

cfsem.vector_potential_circular_filament

vector_potential_circular_filament(
    ifil: NDArray[float64],
    rfil: NDArray[float64],
    zfil: NDArray[float64],
    rprime: NDArray[float64],
    zprime: NDArray[float64],
    par: bool = True,
) -> NDArray[float64]

Vector potential contributions from some circular filaments to some observation points. Off-axis A_phi component for a circular current filament in vacuum.

The vector potential of a loop has zero r- and z- components due to symmetry, and does not vary in the phi-direction.

Note that to recover the B-field as the curl of A, the curl operator for cylindrical coordinates must be used with the output of this function incorporated into a full 3D A-field like [A_r, A_phi, A_z].

References

[1] J. C. Simpson, J. E. Lane, C. D. Immer, R. C. Youngquist, and T. Steinrock, “Simple Analytic Expressions for the Magnetic Field of a Circular Current Loop,” Jan. 01, 2001. Accessed: Sep. 06, 2022. [Online]. Available: https://ntrs.nasa.gov/citations/20010038494

Parameters:

Name Type Description Default
ifil NDArray[float64]

[A] filament current

required
rfil NDArray[float64]

[m] filament R-coord

required
zfil NDArray[float64]

[m] filament Z-coord

required
rprime NDArray[float64]

[m] Observation point R-coord

required
zprime NDArray[float64]

[m] Observation point Z-coord

required
par bool

Whether to use CPU parallelism

True

Returns:

Type Description
NDArray[float64]

[Wb/m] or [V-s/m] a_phi, vector potential in the toroidal direction

Source code in cfsem/bindings.py
def vector_potential_circular_filament(
    ifil: NDArray[float64],
    rfil: NDArray[float64],
    zfil: NDArray[float64],
    rprime: NDArray[float64],
    zprime: NDArray[float64],
    par: bool = True,
) -> NDArray[float64]:
    """
    Vector potential contributions from some circular filaments to some observation points.
    Off-axis A_phi component for a circular current filament in vacuum.

    The vector potential of a loop has zero r- and z- components due to symmetry,
    and does not vary in the phi-direction.

    Note that to recover the B-field as the curl of A, the curl operator for cylindrical
    coordinates must be used with the output of this function incorporated into a full
    3D A-field like [A_r, A_phi, A_z].

    References:
        [1] J. C. Simpson, J. E. Lane, C. D. Immer, R. C. Youngquist, and T. Steinrock,
            “Simple Analytic Expressions for the Magnetic Field of a Circular Current Loop,”
            Jan. 01, 2001. Accessed: Sep. 06, 2022. [Online]. Available: <https://ntrs.nasa.gov/citations/20010038494>

    Args:
        ifil: [A] filament current
        rfil: [m] filament R-coord
        zfil: [m] filament Z-coord
        rprime: [m] Observation point R-coord
        zprime: [m] Observation point Z-coord
        par: Whether to use CPU parallelism

    Returns:
        [Wb/m] or [V-s/m] a_phi, vector potential in the toroidal direction
    """
    ifil, rfil, zfil = _3tup_contig((ifil, rfil, zfil))
    rprime, zprime = _2tup_contig((rprime, zprime))
    a_phi = em_vector_potential_circular_filament(ifil, rfil, zfil, rprime, zprime, par)
    return a_phi  # [Wb/m] or [V-s/m]

cfsem.vector_potential_linear_filament

vector_potential_linear_filament(
    xyzp: Array3xN,
    xyzfil: Array3xN,
    dlxyzfil: Array3xN,
    ifil: NDArray[float64],
    wire_radius: float | NDArray[float64] = 0.0,
    par: bool = True,
    output: Literal["vector", "matrix"] = "vector",
) -> tuple[
    NDArray[float64], NDArray[float64], NDArray[float64]
]

Vector potential calculation for A-field contribution from many current filament segments to many observation points.

Parameters:

Name Type Description Default
xyzp Array3xN

[m] x,y,z coords of observation points

required
xyzfil Array3xN

[m] x,y,z coords of filament segment start points

required
dlxyzfil Array3xN

[m] x,y,z deltas from segment start to segment end

required
ifil NDArray[float64]

[A] current in each filament segment

required
wire_radius float | NDArray[float64]

[m] filament radius, scalar or array of length m

0.0
par bool

Whether to use CPU parallelism

True
output Literal['vector', 'matrix']

"vector" for contracted field values at each target point, or "matrix" for row-major (nobs, nfil) source-target interaction matrices

'vector'

Returns:

Type Description
NDArray[float64]

[Wb/m] or [V-s/m] (Ax, Ay, Az) magnetic vector potential at observation points,

NDArray[float64]

or explicit (nobs, nfil) interaction matrices if output="matrix"

Source code in cfsem/bindings.py
def vector_potential_linear_filament(
    xyzp: Array3xN,
    xyzfil: Array3xN,
    dlxyzfil: Array3xN,
    ifil: NDArray[float64],
    wire_radius: float | NDArray[float64] = 0.0,
    par: bool = True,
    output: Literal["vector", "matrix"] = "vector",
) -> tuple[NDArray[float64], NDArray[float64], NDArray[float64]]:
    """
    Vector potential calculation for A-field contribution from many current filament
    segments to many observation points.

    Args:
        xyzp: [m] x,y,z coords of observation points
        xyzfil: [m] x,y,z coords of filament segment start points
        dlxyzfil: [m] x,y,z deltas from segment start to segment end
        ifil: [A] current in each filament segment
        wire_radius: [m] filament radius, scalar or array of length `m`
        par: Whether to use CPU parallelism
        output: `"vector"` for contracted field values at each target point,
            or `"matrix"` for row-major `(nobs, nfil)` source-target interaction matrices

    Returns:
        [Wb/m] or [V-s/m] (Ax, Ay, Az) magnetic vector potential at observation points,
        or explicit `(nobs, nfil)` interaction matrices if `output="matrix"`
    """
    xyzp = _3tup_contig(xyzp)
    xyzfil = _3tup_contig(xyzfil)
    dlxyzfil = _3tup_contig(dlxyzfil)
    ifil = ascontiguousarray(ifil).ravel()
    if asarray(wire_radius).ndim == 0:
        wire_radius = full(ifil.size, float(wire_radius))
    wire_radius = ascontiguousarray(wire_radius).ravel()
    if output == "vector":
        return em_vector_potential_linear_filament(xyzp, xyzfil, dlxyzfil, ifil, wire_radius, par)
    if output == "matrix":
        ax, ay, az = em_vector_potential_linear_filament_matrix(
            xyzp, xyzfil, dlxyzfil, ifil, wire_radius, par
        )
        nobs = xyzp[0].size
        nfil = ifil.size
        return (
            ax.reshape((nobs, nfil)),
            ay.reshape((nobs, nfil)),
            az.reshape((nobs, nfil)),
        )
    raise ValueError("output must be 'vector' or 'matrix'")

cfsem.vector_potential_triangle_mesh

vector_potential_triangle_mesh(
    obs: NDArray[float64],
    nodes: NDArray[float64],
    triangles: NDArray[int64],
    s: NDArray[float64],
    par: bool = True,
    quad: str = "dunavant3",
) -> Array3xN

Vector potential calculation for A-field contribution from a triangle mesh with one stream-function value per node.

Parameters:

Name Type Description Default
obs NDArray[float64]

[m] observation points with shape (nobs, 3)

required
nodes NDArray[float64]

[m] mesh node coordinates with shape (nnode, 3)

required
triangles NDArray[int64]

node indices with shape (ntri, 3)

required
s NDArray[float64]

[A] nodal stream-function values with shape (nnode,)

required
par bool

Whether to use CPU parallelism

True
quad str

Triangle quadrature rule, one of "dunavant1", "dunavant2", "dunavant3", "dunavant4", or "dunavant5"

'dunavant3'

Returns:

Type Description
Array3xN

[Wb/m] or [V-s/m] (Ax, Ay, Az) magnetic vector potential at observation points

Source code in cfsem/bindings.py
def vector_potential_triangle_mesh(
    obs: NDArray[float64],
    nodes: NDArray[float64],
    triangles: NDArray[int64],
    s: NDArray[float64],
    par: bool = True,
    quad: str = "dunavant3",
) -> Array3xN:
    """
    Vector potential calculation for A-field contribution from a triangle mesh
    with one stream-function value per node.

    Args:
        obs: [m] observation points with shape `(nobs, 3)`
        nodes: [m] mesh node coordinates with shape `(nnode, 3)`
        triangles: node indices with shape `(ntri, 3)`
        s: [A] nodal stream-function values with shape `(nnode,)`
        par: Whether to use CPU parallelism
        quad: Triangle quadrature rule, one of `"dunavant1"`, `"dunavant2"`,
            `"dunavant3"`, `"dunavant4"`, or `"dunavant5"`

    Returns:
        [Wb/m] or [V-s/m] (Ax, Ay, Az) magnetic vector potential at observation points
    """
    obs = ascontiguousarray(obs, dtype=float64)
    nodes = ascontiguousarray(nodes, dtype=float64)
    triangles = ascontiguousarray(triangles, dtype=int64)
    s = ascontiguousarray(s, dtype=float64).ravel()
    return em_vector_potential_triangle_mesh(obs, nodes, triangles, s, par, quad)

cfsem.vector_potential_point_segment

vector_potential_point_segment(
    xyzp: Array3xN,
    xyzfil: Array3xN,
    dlxyzfil: Array3xN,
    ifil: NDArray[float64],
    par: bool = True,
) -> Array3xN

Vector potential calculation for A-field contribution from many filament segments to many observation points, treating each segment as a point source.

Parameters:

Name Type Description Default
xyzp Array3xN

[m] x,y,z coords of observation points

required
xyzfil Array3xN

[m] x,y,z coords of filament segment start points

required
dlxyzfil Array3xN

[m] x,y,z deltas from segment start to segment end

required
ifil NDArray[float64]

[A] current in each filament segment

required
par bool

Whether to use CPU parallelism

True

Returns:

Type Description
Array3xN

[Wb/m] or [V-s/m] (Ax, Ay, Az) magnetic vector potential at observation points

Source code in cfsem/bindings.py
def vector_potential_point_segment(
    xyzp: Array3xN,
    xyzfil: Array3xN,
    dlxyzfil: Array3xN,
    ifil: NDArray[float64],
    par: bool = True,
) -> Array3xN:
    """
    Vector potential calculation for A-field contribution from many filament
    segments to many observation points, treating each segment as a point source.

    Args:
        xyzp: [m] x,y,z coords of observation points
        xyzfil: [m] x,y,z coords of filament segment start points
        dlxyzfil: [m] x,y,z deltas from segment start to segment end
        ifil: [A] current in each filament segment
        par: Whether to use CPU parallelism

    Returns:
        [Wb/m] or [V-s/m] (Ax, Ay, Az) magnetic vector potential at observation points
    """
    xyzp = _3tup_contig(xyzp)
    xyzfil = _3tup_contig(xyzfil)
    dlxyzfil = _3tup_contig(dlxyzfil)
    ifil = ascontiguousarray(ifil).ravel()
    return em_vector_potential_point_segment(xyzp, xyzfil, dlxyzfil, ifil, par)