Skip to content

Filaments and paths

cfsem.filament_coil

filament_coil(
    r: float,
    z: float,
    w: float,
    h: float,
    nt: float,
    nr: int,
    nz: int,
) -> NDArray

Create an array of filaments from coil cross-section, evenly spaced inside the winding pack. No filaments are coincident with the coil surface.

Parameters:

Name Type Description Default
r float

[m] radius, coil center

required
z float

[m] axial position, coil center

required
w float

[m] width of coil pack

required
h float

[m] height of coil pack

required
nt float

turns

required
nr int

radial discretizations

required
nz int

axial discretizations

required

Returns:

Type Description
NDArray

(nr*nz) x 3, (r,z,n) of each filament

Source code in cfsem/__init__.py
def filament_coil(r: float, z: float, w: float, h: float, nt: float, nr: int, nz: int) -> NDArray:
    """
    Create an array of filaments from coil cross-section, evenly spaced
    _inside_ the winding pack. No filaments are coincident with the coil surface.

    Args:
        r: [m] radius, coil center
        z: [m] axial position, coil center
        w: [m] width of coil pack
        h: [m] height of coil pack
        nt: turns
        nr: radial discretizations
        nz: axial discretizations

    Returns:
        (nr*nz) x 3, (r,z,n) of each filament
    """

    # Build a 2D mesh of points evenly spaced in the interior of the bounding rectangle
    rs = np.linspace(r - w * (nr - 1) / nr / 2, r + w * (nr - 1) / nr / 2, nr)  # [m]
    zs = np.linspace(z - h * (nz - 1) / nz / 2, z + h * (nz - 1) / nz / 2, nz)  # [m]
    rmesh, zmesh = np.meshgrid(rs, zs, indexing="ij")  # [m]

    # Number of turns attributed to each point is not necessarily an integer
    n = np.full_like(rmesh.ravel(), float(nt) / (nr * nz))

    # Pack filament locations and number of turns into an array together
    filaments = np.dstack([rmesh.ravel(), zmesh.ravel(), n]).reshape(nr * nz, 3)

    return filaments  # [m], [m], [dimensionless]

cfsem.filament_helix_path

filament_helix_path(
    path: Array3xN,
    helix_start_offset: tuple[float, float, float],
    twist_pitch: float,
    angle_offset: float,
) -> Array3xN

Filamentize a helix about an arbitrary piecewise-linear path.

Assumes angle between sequential path segments is small and will fail if that angle approaches or exceeds 90 degrees.

The helix initial position vector, helix_start_offset, must be in a plane normal to the first path segment in order to produce good results. If it is not in-plane, it will be projected on to that plane and then scaled to the magnitude of its original length s.t. the distance from the helix to the path center is preserved but its orientation is not.

Description of the method:

  1. Translate [filament segment n-1] to the base of [path segment n] and call it [filament segment n]
  2. Take cross product of [path segment n] with [path segment n-1]
  3. Rotate [filament segment n] segment about the axis of that cross product to bring it into the plane defined by [path segment n] as a normal vector
  4. Rotate [filament seg. n] about [path seg. n] to continue the helix orbit

Parameters:

Name Type Description Default
path Array3xN

[m] 3xN Centerline points

required
helix_start_offset tuple[float, float, float]

[m] (3x1) Initial position of helix rel. to centerline path

required
twist_pitch float

[m] (scalar) Centerline length per helix orbit

required
angle_offset float

[rad] (scalar) Initial rotation offset about centerline

required

Returns:

Type Description
Array3xN

[m] 3xN array of points on the helix that twists around the path

Source code in cfsem/bindings.py
def filament_helix_path(
    path: Array3xN,
    helix_start_offset: tuple[float, float, float],
    twist_pitch: float,
    angle_offset: float,
) -> Array3xN:
    """
    Filamentize a helix about an arbitrary piecewise-linear path.

    Assumes angle between sequential path segments is small and will fail
    if that angle approaches or exceeds 90 degrees.

    The helix initial position vector, helix_start_offset, must be in a plane normal to
    the first path segment in order to produce good results. If it is not in-plane,
    it will be projected on to that plane and then scaled to the magnitude of its
    original length s.t. the distance from the helix to the path center is preserved
    but its orientation is not.

    Description of the method:

    1. Translate [filament segment n-1] to the base of [path segment n]
        and call it [filament segment n]
    2. Take cross product of [path segment n] with [path segment n-1]
    3. Rotate [filament segment n] segment about the axis of that cross product
        to bring it into the plane defined by [path segment n] as a normal vector
    4. Rotate [filament seg. n] about [path seg. n] to continue the helix orbit

    Args:
        path: [m] 3xN Centerline points
        helix_start_offset: [m] (3x1) Initial position of helix rel. to centerline path
        twist_pitch: [m] (scalar) Centerline length per helix orbit
        angle_offset: [rad] (scalar) Initial rotation offset about centerline

    Returns:
        [m] 3xN array of points on the helix that twists around the path
    """

    # Make sure input is contiguous, reallocating only if necessary
    path = ascontiguousarray(path)

    # Allocate output
    helix = zeros_like(path)  # [m]

    # Calculate, mutating output
    em_filament_helix_path(
        (*path,),
        helix_start_offset,
        twist_pitch,
        angle_offset,
        (*helix,),
    )

    return helix  # [m]

cfsem.rotate_filaments_about_path

rotate_filaments_about_path(
    path: Array3xN, angle_offset: float, fils: Array3xN
) -> Array3xN

Rotate a path of point about another path.

Intended for rotating a helix generated by filament_helix_path about the centerline that was used to generate it.

Parameters:

Name Type Description Default
path Array3xN

[m] x,y,z Centerline points

required
angle_offset float

[rad] (scalar) Initial rotation offset about centerline

required
fils Array3xN

[m] x,y,z Filaments to rotate around centerline

required

Returns:

Type Description
Array3xN

[m] 3xN array of points on the helix that twists around the path

Source code in cfsem/bindings.py
def rotate_filaments_about_path(path: Array3xN, angle_offset: float, fils: Array3xN) -> Array3xN:
    """
    Rotate a path of point about another path.

    Intended for rotating a helix generated by [`filament_helix_path`][cfsem.filament_helix_path]
    about the centerline that was used to generate it.

    Args:
        path: [m] x,y,z Centerline points
        angle_offset: [rad] (scalar) Initial rotation offset about centerline
        fils: [m] x,y,z Filaments to rotate around centerline

    Returns:
        [m] 3xN array of points on the helix that twists around the path
    """

    # Make sure input is contiguous, reallocating only if necessary
    path = ascontiguousarray(path)

    new_fils = ascontiguousarray(fils).copy()

    em_rotate_filaments_about_path(
        (*path,),
        angle_offset,
        (*new_fils,),
    )

    return new_fils  # [m]