Geometry¶
Tagged CAD: the geometry seam, tagged build123d shapes, cross-sections, frame conversion, the winding packer and build123d helpers.
femforge.geometry
¶
Tagged CAD infrastructure: the GeometryArea seam, tagged build123d shapes, cross-sections, frame conversion and the winding packer.
Modules:
-
build123d_geometry–A geometry authored as a build123d tagged assembly.
-
config–The parametric-geometry config area: a geometry the driver materializes into a STEP before meshing.
-
frame–Convert an authored STEP into the frame the solve meshes.
-
section–Tagged cross-sections of tagged 3D solids: the quarter-wedge cutaway and the axisymmetric r–z section the 2D solve meshes.
-
tags–Tagged build123d shapes whose tags ride their STEP names into the mesh.
-
utils–build123d helpers: boundary boxes, rectangles, assembly-tree pruning and collinearity checks.
-
winding–Round-wire winding packer: the orthocyclic layer stack a wire settles into in a rectangular window, every wire position, and the derived electrical quantities.
Classes:
-
Build123dGeometry–A
GeometryAreawhose STEP is the export ofmodel, the tagged assembly in the authored frame. -
GeometryArea–A parametric geometry the driver builds into a STEP in the authored frame;
config.frameconverts it for the solve.
Build123dGeometry
pydantic-model
¶
Bases: GeometryArea
A GeometryArea whose STEP is the export of model, the tagged assembly in the authored frame.
Config:
arbitrary_types_allowed:Trueuse_attribute_docstrings:Trueextra:allow
model
abstractmethod
¶
model() -> TaggedCompound
build_step
¶
GeometryArea
pydantic-model
¶
Bases: ConfigArea
A parametric geometry the driver builds into a STEP in the authored frame; config.frame converts it for the solve.
build_step
¶
femforge.geometry.section
¶
Tagged cross-sections of tagged 3D solids: the quarter-wedge cutaway and the axisymmetric r–z section the 2D solve meshes.
Functions:
-
cross_section_3D–Cut away the material on the positive side of every plane, copying each solid's tags and color; raises when the planes share no volume or the wedge consumes a solid whole.
-
axisymmetric_cross_section–Section every tagged solid on the half-plane through
axistowardradialinto the solve frame (X = radial >= 0, Y = along the axis, Z = 0); a missed solid raises.
cross_section_3D
¶
cross_section_3D(compound: TaggedCompound, planes: Iterable[Plane] = (YZ, XY), margin: float = 1.0) -> TaggedCompound
Cut away the material on the positive side of every plane, copying each solid's tags and color; raises when the planes share no volume or the wedge consumes a solid whole.
Parameters:
-
compound(TaggedCompound) –The tagged assembly to cut.
-
planes(Iterable[Plane], default:(YZ, XY)) –The cutting planes; the default cuts away the X >= 0, Z >= 0 quarter wedge.
-
margin(float, default:1.0) –How far the cutting boxes reach past the parts.
Source code in src/femforge/geometry/section.py
axisymmetric_cross_section
¶
axisymmetric_cross_section(compound: TaggedCompound, axis: Axis = Z, radial: Vec3 | None = None, margin: float = 1.0) -> TaggedCompound
Section every tagged solid on the half-plane through axis toward radial into the solve frame (X = radial >= 0, Y = along the axis, Z = 0); a missed solid raises.
Parameters:
-
compound(TaggedCompound) –The tagged assembly to section.
-
axis(Axis, default:Z) –The axis of symmetry.
-
radial(Vec3 | None, default:None) –The direction from the axis toward the half-plane; None picks the world axis least aligned with
axis. -
margin(float, default:1.0) –How far the half-plane reaches past the parts.
Source code in src/femforge/geometry/section.py
femforge.geometry.frame
¶
Convert an authored STEP into the frame the solve meshes.
Functions:
-
import_tagged_step–The STEP's named solids as world-placed
TaggedPartchildren tagged from their name paths. -
apply_frame–The STEP the solve meshes:
step_initself for a solid frame, else its axisymmetric section written tostep_out.
import_tagged_step
¶
import_tagged_step(path: Path) -> TaggedCompound
The STEP's named solids as world-placed TaggedPart children tagged from their name paths.
Source code in src/femforge/geometry/frame.py
apply_frame
¶
The STEP the solve meshes: step_in itself for a solid frame, else its axisymmetric section written to step_out.
Parameters:
-
step_in(Path) –The authored STEP.
-
step_out(Path) –Where an axisymmetric section is written.
-
frame(Frame) –The solve frame.
Source code in src/femforge/geometry/frame.py
femforge.geometry.tags
¶
Tagged build123d shapes whose tags ride their STEP names into the mesh.
Classes:
-
TaggedCompound–A build123d compound whose tags pass down to its tagged leaves on export.
-
TaggedFace–A build123d face whose tags ride its STEP name into a 2D mesh.
-
TaggedSketch–A build123d sketch that carries tags.
-
TaggedPart–A build123d part whose tags ride its STEP name into the mesh.
-
TaggedEdge–A build123d edge that carries tags.
Functions:
-
named–tagswithnameset as itsTagKey.NAMEtag, ortagsunchanged whennameis None.
TaggedCompound
¶
Bases: Compound, HasTags
A build123d compound whose tags pass down to its tagged leaves on export.
Methods:
-
rebuild_labels–Relabel every tagged part below this compound with its tags.
-
placed_leaves–Fresh copies of the tagged solids and faces, world-placed, moved by
location, and carrying their ancestors' tags (deeper wins). -
flatten_and_tag–A new compound of the world-placed tagged leaves (see
placed_leaves), labelled with their tags;selfis left untouched. -
export_step–Export the compound, flattened into its tagged leaves unless
flattenis False, to the STEP filefilename.
Attributes:
-
children_at_global_location(list[Any3D]) –Return a list of children located at their global location.
Source code in src/femforge/geometry/tags.py
children_at_global_location
property
¶
children_at_global_location: list[Any3D]
Return a list of children located at their global location.
rebuild_labels
¶
Relabel every tagged part below this compound with its tags.
placed_leaves
¶
placed_leaves(location: Location | None = None) -> list[TaggedPart | TaggedFace]
Fresh copies of the tagged solids and faces, world-placed, moved by location, and carrying their ancestors' tags (deeper wins).
Source code in src/femforge/geometry/tags.py
flatten_and_tag
¶
A new compound of the world-placed tagged leaves (see placed_leaves), labelled with their tags; self is left untouched.
Source code in src/femforge/geometry/tags.py
export_step
¶
Export the compound, flattened into its tagged leaves unless flatten is False, to the STEP file filename.
Source code in src/femforge/geometry/tags.py
TaggedFace
¶
Bases: Face, HasTags
A build123d face whose tags ride its STEP name into a 2D mesh.
Parameters:
-
face(Face) –The face to wrap, placed where it is.
-
tags(TagDict | None, default:None) –The
key=valuepairs domain materials andEntityTagselectors match, e.g.{TagKey.MATERIAL: N52().tag}. -
name(str | None, default:None) –The body name, kept as written in the
Nametag and uppercased in the mesh, Elmer,entities.jsonand the viewer; None composes it from the tags.
Source code in src/femforge/geometry/tags.py
TaggedSketch
¶
Bases: Sketch, HasTags
A build123d sketch that carries tags.
Source code in src/femforge/geometry/tags.py
TaggedPart
¶
Bases: Part, HasTags
A build123d part whose tags ride its STEP name into the mesh.
Parameters:
-
shapes(Iterable[AnyShape]) –The solids the part holds, such as
[box]or a build123d part. -
tags(TagDict | None, default:None) –The
key=valuepairs domain materials andEntityTagselectors match, e.g.{TagKey.MATERIAL: N52().tag}. -
name(str | None, default:None) –The body name, kept as written in the
Nametag and uppercased in the mesh, Elmer,entities.jsonand the viewer; None composes it from the tags.
Source code in src/femforge/geometry/tags.py
TaggedEdge
¶
TaggedEdge(edge: Edge, *, tags: TagDict | None = None)
Bases: Edge, HasTags
A build123d edge that carries tags.
Source code in src/femforge/geometry/tags.py
named
¶
tags with name set as its TagKey.NAME tag, or tags unchanged when name is None.
femforge.geometry.winding
¶
Round-wire winding packer: the orthocyclic layer stack a wire settles into in a rectangular window, every wire position, and the derived electrical quantities.
Classes:
-
OuterDiameterFit–How the specified window OD bounds the layer stack.
-
LengthFit–How the wires occupy the specified window length.
-
Wire–Round magnet wire.
-
CoilWindow–One coil's revolved winding window: the annular slot between the mandrel and the coil OD.
-
WireTurn–One turn's centerline circle.
-
WoundCoil–One packed coil, computed by
wind; every quantity derives from the wire and window alone.
LengthFit
¶
Bases: StrEnum
How the wires occupy the specified window length.
Attributes:
-
TANGENT–The largest integer count of mutually tangent wires, centered in the window; an end gap likely remains.
-
SPLAYED–The base layer spans the window wall to wall: the same wire count, splayed to an axial pitch above the wire OD.
TANGENT
class-attribute
instance-attribute
¶
The largest integer count of mutually tangent wires, centered in the window; an end gap likely remains.
SPLAYED
class-attribute
instance-attribute
¶
The base layer spans the window wall to wall: the same wire count, splayed to an axial pitch above the wire OD.
Wire
dataclass
¶
Round magnet wire.
Attributes:
-
copper_diameter(float) –d_cu[m]: Bare copper diameter. -
insulation_diameter(float) –d_ins[m]: Overall diameter including the enamel. -
copper_area(float) –a_cu[m²]: Bare copper cross-section. -
insulation_area(float) –a_ins[m²]: Insulated-wire cross-section.
CoilWindow
dataclass
¶
One coil's revolved winding window: the annular slot between the mandrel and the coil OD.
Attributes:
-
inner_radius(float) –r_in[m]: Radius of the window's inner wall, where the first layer seats. -
outer_radius(float) –r_out[m]: Radius of the window's outer wall (the CAD coil OD); the last layer may stand proud of it under OVER fit. -
length(float) –w[m]: Axial length of the window: the coil width, which the geometry sets equal to the magnet length. -
area(float) –A_w[m²]: The r-z cross-section of the window: radial depth × axial length. -
mean_radius(float) –r_mean[m]: Mid-radius of the window. -
volume(float) –V_w[m³]: The revolved window volume, 2π·r_mean·A_w.
inner_radius
instance-attribute
¶
inner_radius: float
r_in [m]: Radius of the window's inner wall, where the first layer seats.
outer_radius
instance-attribute
¶
outer_radius: float
r_out [m]: Radius of the window's outer wall (the CAD coil OD); the last layer may stand proud of it under OVER fit.
length
instance-attribute
¶
length: float
w [m]: Axial length of the window: the coil width, which the geometry sets equal to the magnet length.
WireTurn
dataclass
¶
One turn's centerline circle.
Attributes:
WoundCoil
dataclass
¶
WoundCoil(wire: Wire, window: CoilWindow, outer_diameter_fit: OuterDiameterFit, length_fit: LengthFit, axial_pitch: float, radial_pitch: float, turns_per_layer: tuple[int, ...])
One packed coil, computed by wind; every quantity derives from the wire and window alone.
Methods:
-
wind–Pack the wire into the window: nested layers alternate n and n-1 turns, upper wires tangent in the grooves of the layer below.
-
wire_coordinates–Every turn's centerline circle, layer-major; odd layers sit in the grooves, offset by half the axial pitch.
-
coil_resistance–R_coil[Ω]: Per-coil DC resistance attemperature(K), by the same α law the FEA's σ(T) emits. -
window_current_density–J[A/m²]: Homogenized azimuthal current density (signed): the ampere-turns spread over the specified window area — the FEA coil body's drive. -
heat_density–q[W/m³]: Per-coil Joule density, I²·R_coil(T) over the revolved window volume. -
wire_current_density–J_wire[A/m²]: Current density in the copper itself.
Attributes:
-
wire(Wire) –The wound wire.
-
window(CoilWindow) –The window the wire fills.
-
outer_diameter_fit(OuterDiameterFit) –Whether the stack stops under or just over the specified window OD.
-
length_fit(LengthFit) –Whether the base layer is tangent-packed or splayed wall to wall.
-
axial_pitch(float) –p_z[m]: Center-to-center spacing of neighbouring turns in a layer: the wire OD when tangent, wider when splayed. -
radial_pitch(float) –p_r[m]: Center-to-center radial rise from one layer to the next, the groove-nested √(d² − (p_z/2)²). -
turns_per_layer(tuple[int, ...]) –Turn count of each layer from the inside out; nested layers alternate n and n − 1.
-
turns(int) –N[-]: Wire turns in the coil. -
num_layers(int) –The number of layers in the stack.
-
layer_radii(tuple[float, ...]) –[m]: Each layer's wire-center radius, layer 0 seated on the window's inner radius. -
actual_outer_diameter(float) –[m]: The built coil's outer diameter: the outermost layer plus one wire radius. -
actual_length(float) –[m]: The base layer's axial extent; upper layers are inset by half a pitch and never wider. -
end_margin(float) –[m]: The gap between the base layer and each window wall (zero when splayed). -
splay_gap(float) –[m]: The clearance between neighbouring wires in a layer (zero when tangent). -
wire_length(float) –ℓ_wire[m]: Total wire length: each turn's circumference with the helical advance of one axial pitch. -
copper_mass(float) –m_wire[kg]: Copper mass of the wire: length × bare-copper section × the Copper material's density. -
copper_fill_factor(float) –f_cu[-]: Copper cross-section over the specified window cross-section. -
mechanical_fill_factor(float) –f_mech[-]: Insulated-wire cross-section over the specified window cross-section; hex packing bounds it at π/(2√3) ≈ 0.907.
outer_diameter_fit
instance-attribute
¶
outer_diameter_fit: OuterDiameterFit
Whether the stack stops under or just over the specified window OD.
length_fit
instance-attribute
¶
length_fit: LengthFit
Whether the base layer is tangent-packed or splayed wall to wall.
axial_pitch
instance-attribute
¶
axial_pitch: float
p_z [m]: Center-to-center spacing of neighbouring turns in a layer: the wire OD when tangent, wider when splayed.
radial_pitch
instance-attribute
¶
radial_pitch: float
p_r [m]: Center-to-center radial rise from one layer to the next, the groove-nested √(d² − (p_z/2)²).
turns_per_layer
instance-attribute
¶
Turn count of each layer from the inside out; nested layers alternate n and n − 1.
layer_radii
property
¶
[m]: Each layer's wire-center radius, layer 0 seated on the window's inner radius.
actual_outer_diameter
property
¶
actual_outer_diameter: float
[m]: The built coil's outer diameter: the outermost layer plus one wire radius.
actual_length
property
¶
actual_length: float
[m]: The base layer's axial extent; upper layers are inset by half a pitch and never wider.
end_margin
property
¶
end_margin: float
[m]: The gap between the base layer and each window wall (zero when splayed).
splay_gap
property
¶
splay_gap: float
[m]: The clearance between neighbouring wires in a layer (zero when tangent).
wire_length
property
¶
wire_length: float
ℓ_wire [m]: Total wire length: each turn's circumference with the helical advance of one axial pitch.
copper_mass
property
¶
copper_mass: float
m_wire [kg]: Copper mass of the wire: length × bare-copper section × the Copper material's density.
copper_fill_factor
property
¶
copper_fill_factor: float
f_cu [-]: Copper cross-section over the specified window cross-section.
mechanical_fill_factor
property
¶
mechanical_fill_factor: float
f_mech [-]: Insulated-wire cross-section over the specified window cross-section; hex packing bounds it at π/(2√3) ≈ 0.907.
wind
classmethod
¶
wind(wire: Wire, window: CoilWindow, outer_diameter_fit: OuterDiameterFit = UNDER, length_fit: LengthFit = TANGENT) -> WoundCoil
Pack the wire into the window: nested layers alternate n and n-1 turns, upper wires tangent in the grooves of the layer below.
Parameters:
-
wire(Wire) –The wire to wind.
-
window(CoilWindow) –The window to fill.
-
outer_diameter_fit(OuterDiameterFit, default:UNDER) –Whether the stack stops under or just over the window OD.
-
length_fit(LengthFit, default:TANGENT) –Whether the base layer is tangent-packed or splayed wall to wall.
Source code in src/femforge/geometry/winding.py
wire_coordinates
¶
Every turn's centerline circle, layer-major; odd layers sit in the grooves, offset by half the axial pitch.
Source code in src/femforge/geometry/winding.py
coil_resistance
¶
R_coil [Ω]: Per-coil DC resistance at temperature (K), by the same α law the FEA's σ(T) emits.
Source code in src/femforge/geometry/winding.py
window_current_density
¶
J [A/m²]: Homogenized azimuthal current density (signed): the ampere-turns spread over the specified window area — the FEA coil body's drive.
Source code in src/femforge/geometry/winding.py
heat_density
¶
q [W/m³]: Per-coil Joule density, I²·R_coil(T) over the revolved window volume.
Source code in src/femforge/geometry/winding.py
wire_current_density
¶
femforge.geometry.utils
¶
build123d helpers: boundary boxes, rectangles, assembly-tree pruning and collinearity checks.
Classes:
-
Rect–An axis-aligned 2D rectangle of build123d vectors, with edge and corner accessors.
-
NestedRect–The frame-shaped region between an inner and an outer rectangle.
Functions:
-
create_debug_arrow–A debug arrow part on
axis, for the viewer. -
boundary_box–A translucent box around
shape's bounding box, grown bypaddingalong each axis, half on each side. -
remove_where–Filter nodes based on criteria and automatically vacuum empty leftover compounds.
-
are_colliinear–Check if three points are collinear within a given tolerance.
-
all_colliinear–Check if all points in the list are collinear within a given tolerance.
-
drop_collinear_points–pointswith interior points that continue the previous direction dropped (endpoints kept). -
collinear_ends–Assume points are collinear, find the furthest and closest point along that line
-
compound_topology–A rich tree of
compound's descendants, by type and label.
Rect
¶
Rect(min: V | None = None, max: V | None = None, label: str = '')
An axis-aligned 2D rectangle of build123d vectors, with edge and corner accessors.
Parameters:
-
min(V | None, default:None) –The lower-left corner; None is the origin.
-
max(V | None, default:None) –The upper-right corner; None is the origin.
-
label(str, default:'') –A name shown in the repr.
Attributes:
-
left(float) –The x of the left edge; setting it moves only that edge.
-
right(float) –The x of the right edge; setting it moves only that edge.
-
bottom(float) –The y of the bottom edge; setting it moves only that edge.
-
top(float) –The y of the top edge; setting it moves only that edge.
-
width(float) –The extent along x.
-
height(float) –The extent along y.
-
size(V) –The width and height as a vector.
-
center(V) –The midpoint.
-
corners(list[V]) –The four corners, counter-clockwise from
min. -
points(list[V]) –The four corners, the same as
corners.
Source code in src/femforge/geometry/utils.py
NestedRect
¶
The frame-shaped region between an inner and an outer rectangle.
Parameters:
-
inside(Rect | None, default:None) –The inner rectangle; None starts an empty one.
-
outside(Rect | None, default:None) –The outer rectangle; None starts an empty one.
-
label(str, default:'') –A name for the region and its faces; empty derives one from the object id.
Methods:
-
face–Return a face representing the area between the inside and outside rectangles.
-
extrude–Return a part representing the area between the inside and outside rectangles extruded to the given thickness.
Source code in src/femforge/geometry/utils.py
face
¶
Return a face representing the area between the inside and outside rectangles.
Source code in src/femforge/geometry/utils.py
create_debug_arrow
¶
create_debug_arrow(axis: Axis, length: float = 10, radius: float = 0.2, color: Color = Color('cyan')) -> Part
A debug arrow part on axis, for the viewer.
Parameters:
-
axis(Axis) –The axis the arrow starts on and points along.
-
length(float, default:10) –The overall length.
-
radius(float, default:0.2) –The stem radius; the head is 2.5 times wider.
-
color(Color, default:Color('cyan')) –The arrow's color.
Source code in src/femforge/geometry/utils.py
boundary_box
¶
A translucent box around shape's bounding box, grown by padding along each axis, half on each side.
Source code in src/femforge/geometry/utils.py
remove_where
¶
Filter nodes based on criteria and automatically vacuum empty leftover compounds.
Source code in src/femforge/geometry/utils.py
are_colliinear
¶
Check if three points are collinear within a given tolerance.
Parameters:
-
p1(V) –The first point.
-
p2(V) –The middle point.
-
p3(V) –The last point.
-
tolerance(float, default:1e-09) –The largest cross product of the two segments still counted as collinear.
Source code in src/femforge/geometry/utils.py
all_colliinear
¶
Check if all points in the list are collinear within a given tolerance.
Source code in src/femforge/geometry/utils.py
drop_collinear_points
¶
points with interior points that continue the previous direction dropped (endpoints kept).
Source code in src/femforge/geometry/utils.py
collinear_ends
¶
Assume points are collinear, find the furthest and closest point along that line
Source code in src/femforge/geometry/utils.py
compound_topology
¶
A rich tree of compound's descendants, by type and label.