Skip to content

Sections — g.sections

Parametric structural cross-section builders. Each method creates 3D geometry directly in the active session and returns an Instance with named sub-regions (flanges, web, end faces) ready for constraints and loads.

g.sections

apeGmsh.sections._builder.SectionsBuilder

SectionsBuilder(parent: '_SessionBase')

Bases: _HasLogging

Direct in-session section builder (g.sections).

Source code in src/apeGmsh/sections/_builder.py
def __init__(self, parent: "_SessionBase") -> None:
    self._parent = parent

W_solid

W_solid(bf: float, tf: float, h: float, tw: float, length: float, *, anchor='start', align='z', label: str = 'W_solid', lc: float = 1e+22, translate: tuple[float, float, float] = (0.0, 0.0, 0.0), rotate: tuple[float, ...] | None = None) -> 'Instance'

Build a W-shape solid directly in the current session.

Same geometry as :func:apeGmsh.sections.W_solid but without a Part intermediary. Returns an Instance with .labels accessor.

Parameters

anchor : str or (x, y, z), default "start" Re-origin the section in its local frame before optional align and before the user's translate/rotate. See :func:apeGmsh.core._section_placement.compute_anchor_offset. align : str or (ax, ay, az), default "z" Reorient the local +Z axis to a world direction. See :func:apeGmsh.core._section_placement.compute_alignment_rotation. lc : float Target element size for this section's BRep points. Default 1e22 imposes no constraint — element size is governed by :meth:set_global_size alone.

Example

::

with apeGmsh("frame") as g:
    col = g.sections.W_solid(
        bf=150, tf=20, h=300, tw=10, length=2000,
        label="col", lc=50,
    )
    g.mesh.sizing.set_global_size(100)
    g.mesh.generation.generate(3)
Source code in src/apeGmsh/sections/_builder.py
def W_solid(
    self,
    bf: float,
    tf: float,
    h: float,
    tw: float,
    length: float,
    *,
    anchor="start",
    align="z",
    label: str = "W_solid",
    lc: float = 1e22,
    translate: tuple[float, float, float] = (0.0, 0.0, 0.0),
    rotate: tuple[float, ...] | None = None,
) -> "Instance":
    """Build a W-shape solid directly in the current session.

    Same geometry as :func:`apeGmsh.sections.W_solid` but
    without a Part intermediary.  Returns an Instance with
    ``.labels`` accessor.

    Parameters
    ----------
    anchor : str or (x, y, z), default ``"start"``
        Re-origin the section in its local frame before optional
        ``align`` and before the user's ``translate``/``rotate``.
        See :func:`apeGmsh.core._section_placement.compute_anchor_offset`.
    align : str or (ax, ay, az), default ``"z"``
        Reorient the local +Z axis to a world direction.
        See :func:`apeGmsh.core._section_placement.compute_alignment_rotation`.
    lc : float
        Target element size for this section's BRep points.
        Default ``1e22`` imposes no constraint — element size
        is governed by :meth:`set_global_size` alone.

    Example
    -------
    ::

        with apeGmsh("frame") as g:
            col = g.sections.W_solid(
                bf=150, tf=20, h=300, tw=10, length=2000,
                label="col", lc=50,
            )
            g.mesh.sizing.set_global_size(100)
            g.mesh.generation.generate(3)
    """
    def _build():
        geo = self._parent.model.geometry
        boo = self._parent.model.boolean
        tr  = self._parent.model.transforms

        total_h = 2 * tf + h
        outer  = geo.add_rectangle(x=-bf/2, y=-total_h/2, z=0, dx=bf, dy=total_h)
        void_l = geo.add_rectangle(x=-bf/2, y=-h/2, z=0, dx=bf/2-tw/2, dy=h)
        void_r = geo.add_rectangle(x=tw/2,  y=-h/2, z=0, dx=bf/2-tw/2, dy=h)
        boo.cut(outer, [void_l, void_r], dim=2)

        surfs = gmsh.model.getEntities(2)
        if surfs:
            tr.extrude(surfs[0], 0, 0, length)

        geo.slice(axis='x', offset=-tw/2)
        geo.slice(axis='x', offset=tw/2)
        geo.slice(axis='y', offset=h/2)
        geo.slice(axis='y', offset=-h/2)

        # Label volumes by structural role
        labels = self._parent.labels
        # Prefix labels with the instance label
        top_tags, bot_tags, web_tags = [], [], []
        for _, tag in gmsh.model.getEntities(3):
            com = gmsh.model.occ.getCenterOfMass(3, tag)
            if com[1] > h/2:
                top_tags.append(tag)
            elif com[1] < -h/2:
                bot_tags.append(tag)
            else:
                web_tags.append(tag)
        if top_tags:
            labels.add(3, top_tags, name=f"{label}.top_flange")
        if bot_tags:
            labels.add(3, bot_tags, name=f"{label}.bottom_flange")
        if web_tags:
            labels.add(3, web_tags, name=f"{label}.web")

        # End faces
        start_tags, end_tags = [], []
        for _, tag in gmsh.model.getEntities(2):
            try:
                com = gmsh.model.occ.getCenterOfMass(2, tag)
            except Exception:
                continue
            if abs(com[2]) < 1e-3:
                start_tags.append(tag)
            elif abs(com[2] - length) < 1e-3:
                end_tags.append(tag)
        if start_tags:
            labels.add(2, start_tags, name=f"{label}.start_face")
        if end_tags:
            labels.add(2, end_tags, name=f"{label}.end_face")

    return self._build_section(
        _build, label, translate, rotate, lc=lc,
        anchor=anchor, align=align, length=length,
    )

rect_solid

rect_solid(b: float, h: float, length: float, *, anchor='start', align='z', label: str = 'rect', lc: float = 1e+22, translate: tuple[float, float, float] = (0.0, 0.0, 0.0), rotate: tuple[float, ...] | None = None) -> 'Instance'

Build a solid rectangular bar directly in the session.

Parameters

lc : float Target element size for this section's BRep points. Default 1e22 imposes no constraint.

Source code in src/apeGmsh/sections/_builder.py
def rect_solid(
    self,
    b: float,
    h: float,
    length: float,
    *,
    anchor="start",
    align="z",
    label: str = "rect",
    lc: float = 1e22,
    translate: tuple[float, float, float] = (0.0, 0.0, 0.0),
    rotate: tuple[float, ...] | None = None,
) -> "Instance":
    """Build a solid rectangular bar directly in the session.

    Parameters
    ----------
    lc : float
        Target element size for this section's BRep points.
        Default ``1e22`` imposes no constraint.
    """
    def _build():
        tag = self._parent.model.geometry.add_box(
            -b/2, -h/2, 0, b, h, length,
        )
        self._parent.labels.add(3, [tag], name=f"{label}.body")
    return self._build_section(
        _build, label, translate, rotate, lc=lc,
        anchor=anchor, align=align, length=length,
    )

rect_hollow

rect_hollow(b: float, h: float, t: float, length: float, *, anchor='start', align='z', label: str = 'rect_hollow', lc: float = 1e+22, translate: tuple[float, float, float] = (0.0, 0.0, 0.0), rotate: tuple[float, ...] | None = None) -> 'Instance'

Build a hollow rectangular tube (HSS) directly in the session.

Parameters

b : float Outer width (X-direction). h : float Outer height (Y-direction). t : float Wall thickness. length : float Extrusion length (Z-direction). lc : float Target element size. Default 1e22 imposes no constraint.

Source code in src/apeGmsh/sections/_builder.py
def rect_hollow(
    self,
    b: float,
    h: float,
    t: float,
    length: float,
    *,
    anchor="start",
    align="z",
    label: str = "rect_hollow",
    lc: float = 1e22,
    translate: tuple[float, float, float] = (0.0, 0.0, 0.0),
    rotate: tuple[float, ...] | None = None,
) -> "Instance":
    """Build a hollow rectangular tube (HSS) directly in the session.

    Parameters
    ----------
    b : float
        Outer width (X-direction).
    h : float
        Outer height (Y-direction).
    t : float
        Wall thickness.
    length : float
        Extrusion length (Z-direction).
    lc : float
        Target element size. Default ``1e22`` imposes no constraint.
    """
    def _build():
        geo = self._parent.model.geometry
        outer = geo.add_box(-b/2, -h/2, 0, b, h, length)
        inner = geo.add_box(-b/2 + t, -h/2 + t, 0, b - 2*t, h - 2*t, length)
        self._parent.model.boolean.cut(outer, [inner])
        lbl = _PrefixedLabels(self._parent.labels, label)
        for _, tag in gmsh.model.getEntities(3):
            lbl.add(3, [tag], name="body")
            break
        classify_end_faces(length, lbl)

    return self._build_section(
        _build, label, translate, rotate, lc=lc,
        anchor=anchor, align=align, length=length,
    )

pipe_solid

pipe_solid(r: float, length: float, *, anchor='start', align='z', label: str = 'pipe_solid', lc: float = 1e+22, translate: tuple[float, float, float] = (0.0, 0.0, 0.0), rotate: tuple[float, ...] | None = None) -> 'Instance'

Build a solid circular bar directly in the session.

Parameters

r : float Radius. length : float Extrusion length (Z-direction). lc : float Target element size. Default 1e22 imposes no constraint.

Source code in src/apeGmsh/sections/_builder.py
def pipe_solid(
    self,
    r: float,
    length: float,
    *,
    anchor="start",
    align="z",
    label: str = "pipe_solid",
    lc: float = 1e22,
    translate: tuple[float, float, float] = (0.0, 0.0, 0.0),
    rotate: tuple[float, ...] | None = None,
) -> "Instance":
    """Build a solid circular bar directly in the session.

    Parameters
    ----------
    r : float
        Radius.
    length : float
        Extrusion length (Z-direction).
    lc : float
        Target element size. Default ``1e22`` imposes no constraint.
    """
    def _build():
        tag = self._parent.model.geometry.add_cylinder(0, 0, 0, 0, 0, length, r)
        lbl = _PrefixedLabels(self._parent.labels, label)
        lbl.add(3, [tag], name="body")
        classify_end_faces(length, lbl)

    return self._build_section(
        _build, label, translate, rotate, lc=lc,
        anchor=anchor, align=align, length=length,
    )

pipe_hollow

pipe_hollow(r_outer: float, t: float, length: float, *, anchor='start', align='z', label: str = 'pipe_hollow', lc: float = 1e+22, translate: tuple[float, float, float] = (0.0, 0.0, 0.0), rotate: tuple[float, ...] | None = None) -> 'Instance'

Build a hollow circular pipe directly in the session.

Parameters

r_outer : float Outer radius. t : float Wall thickness. length : float Extrusion length (Z-direction). lc : float Target element size. Default 1e22 imposes no constraint.

Source code in src/apeGmsh/sections/_builder.py
def pipe_hollow(
    self,
    r_outer: float,
    t: float,
    length: float,
    *,
    anchor="start",
    align="z",
    label: str = "pipe_hollow",
    lc: float = 1e22,
    translate: tuple[float, float, float] = (0.0, 0.0, 0.0),
    rotate: tuple[float, ...] | None = None,
) -> "Instance":
    """Build a hollow circular pipe directly in the session.

    Parameters
    ----------
    r_outer : float
        Outer radius.
    t : float
        Wall thickness.
    length : float
        Extrusion length (Z-direction).
    lc : float
        Target element size. Default ``1e22`` imposes no constraint.
    """
    def _build():
        geo = self._parent.model.geometry
        outer = geo.add_cylinder(0, 0, 0, 0, 0, length, r_outer)
        inner = geo.add_cylinder(0, 0, 0, 0, 0, length, r_outer - t)
        self._parent.model.boolean.cut(outer, [inner])
        lbl = _PrefixedLabels(self._parent.labels, label)
        for _, tag in gmsh.model.getEntities(3):
            lbl.add(3, [tag], name="body")
            break
        classify_end_faces(length, lbl)

    return self._build_section(
        _build, label, translate, rotate, lc=lc,
        anchor=anchor, align=align, length=length,
    )

angle_solid

angle_solid(b: float, h: float, t: float, length: float, *, anchor='start', align='z', label: str = 'angle_solid', lc: float = 1e+22, translate: tuple[float, float, float] = (0.0, 0.0, 0.0), rotate: tuple[float, ...] | None = None) -> 'Instance'

Build an L-shape (angle) directly in the session.

Parameters

b : float Horizontal leg width (X-direction). h : float Vertical leg height (Y-direction). t : float Thickness of both legs. length : float Extrusion length (Z-direction). lc : float Target element size. Default 1e22 imposes no constraint.

Source code in src/apeGmsh/sections/_builder.py
def angle_solid(
    self,
    b: float,
    h: float,
    t: float,
    length: float,
    *,
    anchor="start",
    align="z",
    label: str = "angle_solid",
    lc: float = 1e22,
    translate: tuple[float, float, float] = (0.0, 0.0, 0.0),
    rotate: tuple[float, ...] | None = None,
) -> "Instance":
    """Build an L-shape (angle) directly in the session.

    Parameters
    ----------
    b : float
        Horizontal leg width (X-direction).
    h : float
        Vertical leg height (Y-direction).
    t : float
        Thickness of both legs.
    length : float
        Extrusion length (Z-direction).
    lc : float
        Target element size. Default ``1e22`` imposes no constraint.
    """
    def _build():
        geo = self._parent.model.geometry
        boo = self._parent.model.boolean
        tr  = self._parent.model.transforms

        h_leg = geo.add_rectangle(x=0, y=0, z=0, dx=b, dy=t)
        v_leg = geo.add_rectangle(x=0, y=0, z=0, dx=t, dy=h)
        boo.fuse([h_leg], [v_leg], dim=2)

        surfs = gmsh.model.getEntities(2)
        if surfs:
            tr.extrude(surfs[0], 0, 0, length)

        geo.slice(axis='x', offset=t)
        geo.slice(axis='y', offset=t)

        lbl = _PrefixedLabels(self._parent.labels, label)
        h_tags, v_tags = [], []
        for _, tag in gmsh.model.getEntities(3):
            com = gmsh.model.occ.getCenterOfMass(3, tag)
            if com[1] < t:
                h_tags.append(tag)
            else:
                v_tags.append(tag)
        if h_tags:
            lbl.add(3, h_tags, name="horizontal_leg")
        if v_tags:
            lbl.add(3, v_tags, name="vertical_leg")
        classify_end_faces(length, lbl)
        classify_angle_outer_faces(lbl)

    return self._build_section(
        _build, label, translate, rotate, lc=lc,
        anchor=anchor, align=align, length=length,
    )

channel_solid

channel_solid(bf: float, tf: float, h: float, tw: float, length: float, *, anchor='start', align='z', label: str = 'channel_solid', lc: float = 1e+22, translate: tuple[float, float, float] = (0.0, 0.0, 0.0), rotate: tuple[float, ...] | None = None) -> 'Instance'

Build a C-shape (channel) directly in the session.

Parameters

bf : float Flange width. tf : float Flange thickness. h : float Clear web height (between flanges). tw : float Web thickness. length : float Extrusion length (Z-direction). lc : float Target element size. Default 1e22 imposes no constraint.

Source code in src/apeGmsh/sections/_builder.py
def channel_solid(
    self,
    bf: float,
    tf: float,
    h: float,
    tw: float,
    length: float,
    *,
    anchor="start",
    align="z",
    label: str = "channel_solid",
    lc: float = 1e22,
    translate: tuple[float, float, float] = (0.0, 0.0, 0.0),
    rotate: tuple[float, ...] | None = None,
) -> "Instance":
    """Build a C-shape (channel) directly in the session.

    Parameters
    ----------
    bf : float
        Flange width.
    tf : float
        Flange thickness.
    h : float
        Clear web height (between flanges).
    tw : float
        Web thickness.
    length : float
        Extrusion length (Z-direction).
    lc : float
        Target element size. Default ``1e22`` imposes no constraint.
    """
    def _build():
        geo = self._parent.model.geometry
        boo = self._parent.model.boolean
        tr  = self._parent.model.transforms

        total_h = h + 2 * tf
        outer = geo.add_rectangle(x=0, y=-total_h/2, z=0, dx=bf, dy=total_h)
        void  = geo.add_rectangle(x=tw, y=-h/2, z=0, dx=bf - tw, dy=h)
        boo.cut(outer, [void], dim=2)

        surfs = gmsh.model.getEntities(2)
        if surfs:
            tr.extrude(surfs[0], 0, 0, length)

        geo.slice(axis='x', offset=tw)
        geo.slice(axis='y', offset=h/2)
        geo.slice(axis='y', offset=-h/2)

        lbl = _PrefixedLabels(self._parent.labels, label)
        classify_w_volumes(h, tw, tf, bf, lbl)
        classify_end_faces(length, lbl)
        classify_w_outer_faces(h, tf, lbl)

    return self._build_section(
        _build, label, translate, rotate, lc=lc,
        anchor=anchor, align=align, length=length,
    )

tee_solid

tee_solid(bf: float, tf: float, h: float, tw: float, length: float, *, anchor='start', align='z', label: str = 'tee_solid', lc: float = 1e+22, translate: tuple[float, float, float] = (0.0, 0.0, 0.0), rotate: tuple[float, ...] | None = None) -> 'Instance'

Build a T-shape (tee) directly in the session.

Parameters

bf : float Flange width. tf : float Flange thickness. h : float Stem height. tw : float Stem thickness. length : float Extrusion length (Z-direction). lc : float Target element size. Default 1e22 imposes no constraint.

Source code in src/apeGmsh/sections/_builder.py
def tee_solid(
    self,
    bf: float,
    tf: float,
    h: float,
    tw: float,
    length: float,
    *,
    anchor="start",
    align="z",
    label: str = "tee_solid",
    lc: float = 1e22,
    translate: tuple[float, float, float] = (0.0, 0.0, 0.0),
    rotate: tuple[float, ...] | None = None,
) -> "Instance":
    """Build a T-shape (tee) directly in the session.

    Parameters
    ----------
    bf : float
        Flange width.
    tf : float
        Flange thickness.
    h : float
        Stem height.
    tw : float
        Stem thickness.
    length : float
        Extrusion length (Z-direction).
    lc : float
        Target element size. Default ``1e22`` imposes no constraint.
    """
    def _build():
        geo = self._parent.model.geometry
        boo = self._parent.model.boolean
        tr  = self._parent.model.transforms

        flange = geo.add_rectangle(x=-bf/2, y=0, z=0, dx=bf, dy=tf)
        stem   = geo.add_rectangle(x=-tw/2, y=-h, z=0, dx=tw, dy=h)
        boo.fuse([flange], [stem], dim=2)

        surfs = gmsh.model.getEntities(2)
        if surfs:
            tr.extrude(surfs[0], 0, 0, length)

        geo.slice(axis='x', offset=-tw/2)
        geo.slice(axis='x', offset=tw/2)
        geo.slice(axis='y', offset=0)

        lbl = _PrefixedLabels(self._parent.labels, label)
        flange_tags, stem_tags = [], []
        for _, tag in gmsh.model.getEntities(3):
            com = gmsh.model.occ.getCenterOfMass(3, tag)
            if com[1] >= 0:
                flange_tags.append(tag)
            else:
                stem_tags.append(tag)
        if flange_tags:
            lbl.add(3, flange_tags, name="flange")
        if stem_tags:
            lbl.add(3, stem_tags, name="stem")
        classify_end_faces(length, lbl)
        classify_tee_outer_faces(h, tf, lbl)

    return self._build_section(
        _build, label, translate, rotate, lc=lc,
        anchor=anchor, align=align, length=length,
    )

W_shell

W_shell(bf: float, tf: float, h: float, tw: float, length: float, *, anchor='start', align='z', label: str = 'W_shell', lc: float = 1e+22, translate: tuple[float, float, float] = (0.0, 0.0, 0.0), rotate: tuple[float, ...] | None = None) -> 'Instance'

Build a W-shape as 3 mid-surface shell rectangles.

Parameters

lc : float Target element size for this section's BRep points. Default 1e22 imposes no constraint.

Source code in src/apeGmsh/sections/_builder.py
def W_shell(
    self,
    bf: float,
    tf: float,
    h: float,
    tw: float,
    length: float,
    *,
    anchor="start",
    align="z",
    label: str = "W_shell",
    lc: float = 1e22,
    translate: tuple[float, float, float] = (0.0, 0.0, 0.0),
    rotate: tuple[float, ...] | None = None,
) -> "Instance":
    """Build a W-shape as 3 mid-surface shell rectangles.

    Parameters
    ----------
    lc : float
        Target element size for this section's BRep points.
        Default ``1e22`` imposes no constraint.
    """
    def _build():
        from apeGmsh.sections.shell import _build_rect_surface
        geo = self._parent.model.geometry
        y_top = h/2 + tf/2
        y_bot = -(h/2 + tf/2)

        _build_rect_surface(
            geo,
            -bf/2, y_top, 0,  bf/2, y_top, 0,
            bf/2, y_top, length,  -bf/2, y_top, length,
            label=f"{label}.top_flange",
        )
        _build_rect_surface(
            geo,
            -bf/2, y_bot, 0,  bf/2, y_bot, 0,
            bf/2, y_bot, length,  -bf/2, y_bot, length,
            label=f"{label}.bottom_flange",
        )
        _build_rect_surface(
            geo,
            0, -h/2, 0,  0, h/2, 0,
            0, h/2, length,  0, -h/2, length,
            label=f"{label}.web",
        )
        self._parent.model.sync()

    return self._build_section(
        _build, label, translate, rotate, lc=lc,
        anchor=anchor, align=align, length=length,
    )

Solid sections

3D volumes suitable for solid elements (dim=3).

apeGmsh.sections.solid.W_solid

W_solid(bf: float, tf: float, h: float, tw: float, length: float, *, anchor='start', align='z', name: str = 'W_solid') -> Part

Create a W-shape (wide flange) as a 3D solid Part.

The section is built as an extruded I-profile, then sliced into 7 hex-compatible volumes by 4 axis-aligned cuts.

Parameters

bf : float Flange width. tf : float Flange thickness. h : float Clear web height (between flanges, not including flanges). tw : float Web thickness. length : float Extrusion length along Z. anchor : str or (x, y, z), default "start" Re-origin the section in its local frame before optional align. See :func:apeGmsh.core._section_placement.compute_anchor_offset. align : str or (ax, ay, az), default "z" Reorient the local +Z axis to a world direction. See :func:apeGmsh.core._section_placement.compute_alignment_rotation. name : str, default "W_solid" Part name.

Labels created

top_flange 3 volumes forming the top flange (y > h/2). bottom_flange 3 volumes forming the bottom flange (y < −h/2). web 1 volume for the web (|y| ≤ h/2). top_flange_face Outer +y skin surfaces of the top flange (face-to-face stacking target for align_to). bottom_flange_face Outer −y skin surfaces of the bottom flange. web_left_face, web_right_face Exposed −x / +x outer faces of the web (within |y| ≤ h/2). start_face, end_face Cross-section profile faces at z=0 and z=length.

Returns

Part

Example

::

col = W_solid(bf=150, tf=20, h=300, tw=10, length=3000)

with apeGmsh("frame") as g:
    g.parts.add(col, label="col_A")
    g.mesh.structured.set_transfinite_automatic()
    g.mesh.sizing.set_global_size(50)
    g.mesh.generation.generate(3)
Source code in src/apeGmsh/sections/solid.py
def W_solid(
    bf: float,
    tf: float,
    h: float,
    tw: float,
    length: float,
    *,
    anchor="start",
    align="z",
    name: str = "W_solid",
) -> Part:
    """Create a W-shape (wide flange) as a 3D solid Part.

    The section is built as an extruded I-profile, then sliced
    into **7 hex-compatible volumes** by 4 axis-aligned cuts.

    Parameters
    ----------
    bf : float
        Flange width.
    tf : float
        Flange thickness.
    h : float
        Clear web height (between flanges, not including flanges).
    tw : float
        Web thickness.
    length : float
        Extrusion length along Z.
    anchor : str or (x, y, z), default ``"start"``
        Re-origin the section in its local frame before optional align.
        See :func:`apeGmsh.core._section_placement.compute_anchor_offset`.
    align : str or (ax, ay, az), default ``"z"``
        Reorient the local +Z axis to a world direction.
        See :func:`apeGmsh.core._section_placement.compute_alignment_rotation`.
    name : str, default "W_solid"
        Part name.

    Labels created
    --------------
    ``top_flange``
        3 volumes forming the top flange (y > h/2).
    ``bottom_flange``
        3 volumes forming the bottom flange (y < −h/2).
    ``web``
        1 volume for the web (|y| ≤ h/2).
    ``top_flange_face``
        Outer +y skin surfaces of the top flange (face-to-face
        stacking target for ``align_to``).
    ``bottom_flange_face``
        Outer −y skin surfaces of the bottom flange.
    ``web_left_face``, ``web_right_face``
        Exposed −x / +x outer faces of the web (within |y| ≤ h/2).
    ``start_face``, ``end_face``
        Cross-section profile faces at z=0 and z=length.

    Returns
    -------
    Part

    Example
    -------
    ::

        col = W_solid(bf=150, tf=20, h=300, tw=10, length=3000)

        with apeGmsh("frame") as g:
            g.parts.add(col, label="col_A")
            g.mesh.structured.set_transfinite_automatic()
            g.mesh.sizing.set_global_size(50)
            g.mesh.generation.generate(3)
    """
    from ._classify import classify_w_volumes

    part = Part(name)
    with part:
        geo = part.model.geometry
        boo = part.model.boolean
        tr  = part.model.transforms

        # Profile: outer rectangle minus two voids
        total_h = 2 * tf + h
        outer  = geo.add_rectangle(x=-bf / 2, y=-total_h / 2, z=0, dx=bf, dy=total_h)
        void_l = geo.add_rectangle(x=-bf / 2, y=-h / 2, z=0, dx=bf / 2 - tw / 2, dy=h)
        void_r = geo.add_rectangle(x=tw / 2,  y=-h / 2, z=0, dx=bf / 2 - tw / 2, dy=h)
        profile = boo.cut(outer, [void_l, void_r], dim=2)

        # Extrude along Z
        tr.extrude(profile, 0, 0, length)

        # Slice into 7 hex-compatible regions
        geo.slice(axis='x', offset=-tw / 2)
        geo.slice(axis='x', offset=tw / 2)
        geo.slice(axis='y', offset=h / 2)
        geo.slice(axis='y', offset=-h / 2)

        # Label by structural role
        classify_w_volumes(h, tw, tf, bf, part.labels)

        # Label end-cap surfaces for BC / load application
        classify_end_faces(length, part.labels)

        # Label outer +y / -y skin surfaces for face-to-face stacking
        classify_w_outer_faces(h, tf, part.labels)
        classify_w_web_side_faces(h, tw, part.labels)

        # Apply anchor + align AFTER classification so the z=0/length
        # end-face heuristic still matches the as-extruded geometry.
        apply_placement(anchor, align, length=length)

    return part

apeGmsh.sections.solid.rect_solid

rect_solid(b: float, h: float, length: float, *, anchor='start', align='z', name: str = 'rect_solid') -> Part

Create a solid rectangular bar as a 3D Part.

Parameters

b : float Width (X-direction). h : float Height (Y-direction). length : float Length (Z-direction). name : str Part name.

Labels created

body — the single volume.

Returns

Part

Source code in src/apeGmsh/sections/solid.py
def rect_solid(
    b: float,
    h: float,
    length: float,
    *,
    anchor="start",
    align="z",
    name: str = "rect_solid",
) -> Part:
    """Create a solid rectangular bar as a 3D Part.

    Parameters
    ----------
    b : float
        Width (X-direction).
    h : float
        Height (Y-direction).
    length : float
        Length (Z-direction).
    name : str
        Part name.

    Labels created
    --------------
    ``body`` — the single volume.

    Returns
    -------
    Part
    """
    part = Part(name)
    with part:
        part.model.geometry.add_box(-b / 2, -h / 2, 0, b, h, length, label="body")
        classify_end_faces(length, part.labels)
        apply_placement(anchor, align, length=length)
    return part

apeGmsh.sections.solid.rect_hollow

rect_hollow(b: float, h: float, t: float, length: float, *, anchor='start', align='z', name: str = 'rect_hollow') -> Part

Create a hollow rectangular tube (HSS) as a 3D solid Part.

Parameters

b : float Outer width (X-direction). h : float Outer height (Y-direction). t : float Wall thickness. length : float Length (Z-direction). name : str Part name.

Labels created

body — the hollow tube volume.

Returns

Part

Source code in src/apeGmsh/sections/solid.py
def rect_hollow(
    b: float,
    h: float,
    t: float,
    length: float,
    *,
    anchor="start",
    align="z",
    name: str = "rect_hollow",
) -> Part:
    """Create a hollow rectangular tube (HSS) as a 3D solid Part.

    Parameters
    ----------
    b : float
        Outer width (X-direction).
    h : float
        Outer height (Y-direction).
    t : float
        Wall thickness.
    length : float
        Length (Z-direction).
    name : str
        Part name.

    Labels created
    --------------
    ``body`` — the hollow tube volume.

    Returns
    -------
    Part
    """
    part = Part(name)
    with part:
        geo = part.model.geometry
        boo = part.model.boolean

        outer = geo.add_box(-b / 2, -h / 2, 0, b, h, length)
        inner = geo.add_box(-b / 2 + t, -h / 2 + t, 0,
                            b - 2 * t, h - 2 * t, length)
        boo.cut(outer, [inner])

        # Label the surviving volume
        for _, tag in gmsh.model.getEntities(3):
            part.labels.add(3, [tag], name="body")
            break
        classify_end_faces(length, part.labels)
        apply_placement(anchor, align, length=length)

    return part

apeGmsh.sections.solid.pipe_solid

pipe_solid(r: float, length: float, *, anchor='start', align='z', name: str = 'pipe_solid') -> Part

Create a solid circular bar as a 3D Part.

Parameters

r : float Radius. length : float Length (Z-direction). name : str Part name.

Labels created

body — the single cylinder volume.

Returns

Part

Source code in src/apeGmsh/sections/solid.py
def pipe_solid(
    r: float,
    length: float,
    *,
    anchor="start",
    align="z",
    name: str = "pipe_solid",
) -> Part:
    """Create a solid circular bar as a 3D Part.

    Parameters
    ----------
    r : float
        Radius.
    length : float
        Length (Z-direction).
    name : str
        Part name.

    Labels created
    --------------
    ``body`` — the single cylinder volume.

    Returns
    -------
    Part
    """
    part = Part(name)
    with part:
        part.model.geometry.add_cylinder(0, 0, 0, 0, 0, length, r, label="body")
        classify_end_faces(length, part.labels)
        apply_placement(anchor, align, length=length)
    return part

apeGmsh.sections.solid.pipe_hollow

pipe_hollow(r_outer: float, t: float, length: float, *, anchor='start', align='z', name: str = 'pipe_hollow') -> Part

Create a hollow circular pipe as a 3D solid Part.

Parameters

r_outer : float Outer radius. t : float Wall thickness. length : float Length (Z-direction). name : str Part name.

Labels created

body — the hollow pipe volume.

Returns

Part

Source code in src/apeGmsh/sections/solid.py
def pipe_hollow(
    r_outer: float,
    t: float,
    length: float,
    *,
    anchor="start",
    align="z",
    name: str = "pipe_hollow",
) -> Part:
    """Create a hollow circular pipe as a 3D solid Part.

    Parameters
    ----------
    r_outer : float
        Outer radius.
    t : float
        Wall thickness.
    length : float
        Length (Z-direction).
    name : str
        Part name.

    Labels created
    --------------
    ``body`` — the hollow pipe volume.

    Returns
    -------
    Part
    """
    part = Part(name)
    with part:
        geo = part.model.geometry
        boo = part.model.boolean

        outer = geo.add_cylinder(0, 0, 0, 0, 0, length, r_outer)
        inner = geo.add_cylinder(0, 0, 0, 0, 0, length, r_outer - t)
        boo.cut(outer, [inner])

        for _, tag in gmsh.model.getEntities(3):
            part.labels.add(3, [tag], name="body")
            break
        classify_end_faces(length, part.labels)
        apply_placement(anchor, align, length=length)

    return part

apeGmsh.sections.solid.angle_solid

angle_solid(b: float, h: float, t: float, length: float, *, anchor='start', align='z', name: str = 'angle_solid') -> Part

Create an L-shape (angle) as a 3D solid Part.

The angle is placed with its corner at the origin, legs extending in +X and +Y. Sliced at the corner junction for hex-compatible meshing.

Parameters

b : float Horizontal leg width (X-direction). h : float Vertical leg height (Y-direction). t : float Thickness of both legs. length : float Extrusion length (Z-direction). name : str Part name.

Labels created

horizontal_leg — volumes in the horizontal leg (y < t). vertical_leg — volumes in the vertical leg (x < t). horizontal_leg_face — underside of h-leg at y=0. vertical_leg_face — back of v-leg at x=0. start_face, end_face — profile faces at z=0 and z=length.

Returns

Part

Source code in src/apeGmsh/sections/solid.py
def angle_solid(
    b: float,
    h: float,
    t: float,
    length: float,
    *,
    anchor="start",
    align="z",
    name: str = "angle_solid",
) -> Part:
    """Create an L-shape (angle) as a 3D solid Part.

    The angle is placed with its corner at the origin, legs
    extending in +X and +Y.  Sliced at the corner junction
    for hex-compatible meshing.

    Parameters
    ----------
    b : float
        Horizontal leg width (X-direction).
    h : float
        Vertical leg height (Y-direction).
    t : float
        Thickness of both legs.
    length : float
        Extrusion length (Z-direction).
    name : str
        Part name.

    Labels created
    --------------
    ``horizontal_leg`` — volumes in the horizontal leg (y < t).
    ``vertical_leg`` — volumes in the vertical leg (x < t).
    ``horizontal_leg_face`` — underside of h-leg at y=0.
    ``vertical_leg_face`` — back of v-leg at x=0.
    ``start_face``, ``end_face`` — profile faces at z=0 and z=length.

    Returns
    -------
    Part
    """
    part = Part(name)
    with part:
        geo = part.model.geometry
        boo = part.model.boolean
        tr  = part.model.transforms

        # Build L-profile as two rectangles fused
        h_leg = geo.add_rectangle(x=0, y=0, z=0, dx=b, dy=t)
        v_leg = geo.add_rectangle(x=0, y=0, z=0, dx=t, dy=h)
        boo.fuse([h_leg], [v_leg], dim=2)

        # Extrude
        surfs = gmsh.model.getEntities(2)
        if surfs:
            tr.extrude(surfs[0], 0, 0, length)

        # Slice at the corner junction
        geo.slice(axis='x', offset=t)
        geo.slice(axis='y', offset=t)

        # Label by structural role
        h_tags = []
        v_tags = []
        for _, tag in gmsh.model.getEntities(3):
            com = gmsh.model.occ.getCenterOfMass(3, tag)
            if com[1] < t:
                h_tags.append(tag)
            else:
                v_tags.append(tag)
        if h_tags:
            part.labels.add(3, h_tags, name="horizontal_leg")
        if v_tags:
            part.labels.add(3, v_tags, name="vertical_leg")
        classify_end_faces(length, part.labels)
        classify_angle_outer_faces(part.labels)
        apply_placement(anchor, align, length=length)

    return part

apeGmsh.sections.solid.channel_solid

channel_solid(bf: float, tf: float, h: float, tw: float, length: float, *, anchor='start', align='z', name: str = 'channel_solid') -> Part

Create a C-shape (channel) as a 3D solid Part.

The channel opens in the +X direction. The web is at x=0, flanges extend in the +X direction from the web.

Parameters

bf : float Flange width (depth of flanges in X). tf : float Flange thickness. h : float Clear web height (between flanges). tw : float Web thickness. length : float Extrusion length (Z-direction). name : str Part name.

Labels created

top_flange — volumes in the top flange (y > h/2). bottom_flange — volumes in the bottom flange (y < −h/2). web — volumes in the web. top_flange_face — outer +y skin of top flange. bottom_flange_face — outer −y skin of bottom flange. start_face, end_face — profile faces at z=0 and z=length.

Returns

Part

Source code in src/apeGmsh/sections/solid.py
def channel_solid(
    bf: float,
    tf: float,
    h: float,
    tw: float,
    length: float,
    *,
    anchor="start",
    align="z",
    name: str = "channel_solid",
) -> Part:
    """Create a C-shape (channel) as a 3D solid Part.

    The channel opens in the +X direction.  The web is at x=0,
    flanges extend in the +X direction from the web.

    Parameters
    ----------
    bf : float
        Flange width (depth of flanges in X).
    tf : float
        Flange thickness.
    h : float
        Clear web height (between flanges).
    tw : float
        Web thickness.
    length : float
        Extrusion length (Z-direction).
    name : str
        Part name.

    Labels created
    --------------
    ``top_flange`` — volumes in the top flange (y > h/2).
    ``bottom_flange`` — volumes in the bottom flange (y < −h/2).
    ``web`` — volumes in the web.
    ``top_flange_face`` — outer +y skin of top flange.
    ``bottom_flange_face`` — outer −y skin of bottom flange.
    ``start_face``, ``end_face`` — profile faces at z=0 and z=length.

    Returns
    -------
    Part
    """
    part = Part(name)
    with part:
        geo = part.model.geometry
        boo = part.model.boolean
        tr  = part.model.transforms

        total_h = h + 2 * tf

        # C-profile: outer rectangle minus one void (the open side)
        outer = geo.add_rectangle(x=0, y=-total_h / 2, z=0, dx=bf, dy=total_h)
        void  = geo.add_rectangle(x=tw, y=-h / 2, z=0, dx=bf - tw, dy=h)
        boo.cut(outer, [void], dim=2)

        # Extrude
        surfs = gmsh.model.getEntities(2)
        if surfs:
            tr.extrude(surfs[0], 0, 0, length)

        # Slice for hex readiness
        geo.slice(axis='x', offset=tw)
        geo.slice(axis='y', offset=h / 2)
        geo.slice(axis='y', offset=-h / 2)

        # Label by role
        from ._classify import classify_w_volumes
        classify_w_volumes(h, tw, tf, bf, part.labels)
        classify_end_faces(length, part.labels)
        classify_w_outer_faces(h, tf, part.labels)
        apply_placement(anchor, align, length=length)

    return part

apeGmsh.sections.solid.tee_solid

tee_solid(bf: float, tf: float, h: float, tw: float, length: float, *, anchor='start', align='z', name: str = 'tee_solid') -> Part

Create a T-shape (tee / WT) as a 3D solid Part.

The flange is at the top (+Y), the stem hangs down. Centered on the web at x=0.

Parameters

bf : float Flange width. tf : float Flange thickness. h : float Stem height (from bottom of flange to bottom of stem). tw : float Stem (web) thickness. length : float Extrusion length (Z-direction). name : str Part name.

Labels created

flange — volumes in the flange. stem — volumes in the stem. flange_face — outer +y skin of the flange (top). stem_face — outer −y skin of the stem (bottom). start_face, end_face — profile faces at z=0 and z=length.

Returns

Part

Source code in src/apeGmsh/sections/solid.py
def tee_solid(
    bf: float,
    tf: float,
    h: float,
    tw: float,
    length: float,
    *,
    anchor="start",
    align="z",
    name: str = "tee_solid",
) -> Part:
    """Create a T-shape (tee / WT) as a 3D solid Part.

    The flange is at the top (+Y), the stem hangs down.  Centered
    on the web at x=0.

    Parameters
    ----------
    bf : float
        Flange width.
    tf : float
        Flange thickness.
    h : float
        Stem height (from bottom of flange to bottom of stem).
    tw : float
        Stem (web) thickness.
    length : float
        Extrusion length (Z-direction).
    name : str
        Part name.

    Labels created
    --------------
    ``flange`` — volumes in the flange.
    ``stem`` — volumes in the stem.
    ``flange_face`` — outer +y skin of the flange (top).
    ``stem_face`` — outer −y skin of the stem (bottom).
    ``start_face``, ``end_face`` — profile faces at z=0 and z=length.

    Returns
    -------
    Part
    """
    part = Part(name)
    with part:
        geo = part.model.geometry
        boo = part.model.boolean
        tr  = part.model.transforms

        # T-profile: flange rectangle + stem rectangle, fused
        flange = geo.add_rectangle(x=-bf / 2, y=0, z=0, dx=bf, dy=tf)
        stem   = geo.add_rectangle(x=-tw / 2, y=-h, z=0, dx=tw, dy=h)
        boo.fuse([flange], [stem], dim=2)

        surfs = gmsh.model.getEntities(2)
        if surfs:
            tr.extrude(surfs[0], 0, 0, length)

        # Slice at the flange-stem junction
        geo.slice(axis='x', offset=-tw / 2)
        geo.slice(axis='x', offset=tw / 2)
        geo.slice(axis='y', offset=0)

        # Label by role
        flange_tags = []
        stem_tags = []
        for _, tag in gmsh.model.getEntities(3):
            com = gmsh.model.occ.getCenterOfMass(3, tag)
            if com[1] >= 0:
                flange_tags.append(tag)
            else:
                stem_tags.append(tag)
        if flange_tags:
            part.labels.add(3, flange_tags, name="flange")
        if stem_tags:
            part.labels.add(3, stem_tags, name="stem")
        classify_end_faces(length, part.labels)
        classify_tee_outer_faces(h, tf, part.labels)
        apply_placement(anchor, align, length=length)

    return part

Shell sections

Mid-surface geometry for shell elements (dim=2).

apeGmsh.sections.shell.W_shell

W_shell(bf: float, tf: float, h: float, tw: float, length: float, *, anchor='start', align='z', name: str = 'W_shell') -> Part

Create a W-shape as 3 mid-surface shell rectangles.

The I-section is represented by:

  • top flange — horizontal rectangle at y = h/2 + tf/2 (flange mid-plane), width bf, length length.
  • bottom flange — horizontal rectangle at y = -(h/2 + tf/2).
  • web — vertical rectangle at x = 0, height h, length length.

Parameters

bf : float Flange width. tf : float Flange thickness (positions the mid-surface; the shell element's section definition carries the actual thickness). h : float Clear web height (between flange mid-surfaces). tw : float Web thickness (informational — the mid-surface is at x=0). length : float Extrusion length along Z. name : str Part name.

Labels created

top_flange The top flange mid-surface. bottom_flange The bottom flange mid-surface. web The web mid-surface.

Returns

Part

Source code in src/apeGmsh/sections/shell.py
def W_shell(
    bf: float,
    tf: float,
    h: float,
    tw: float,
    length: float,
    *,
    anchor="start",
    align="z",
    name: str = "W_shell",
) -> Part:
    """Create a W-shape as 3 mid-surface shell rectangles.

    The I-section is represented by:

    * **top flange** — horizontal rectangle at ``y = h/2 + tf/2``
      (flange mid-plane), width ``bf``, length ``length``.
    * **bottom flange** — horizontal rectangle at ``y = -(h/2 + tf/2)``.
    * **web** — vertical rectangle at ``x = 0``, height ``h``,
      length ``length``.

    Parameters
    ----------
    bf : float
        Flange width.
    tf : float
        Flange thickness (positions the mid-surface; the shell
        element's section definition carries the actual thickness).
    h : float
        Clear web height (between flange mid-surfaces).
    tw : float
        Web thickness (informational — the mid-surface is at x=0).
    length : float
        Extrusion length along Z.
    name : str
        Part name.

    Labels created
    --------------
    ``top_flange``
        The top flange mid-surface.
    ``bottom_flange``
        The bottom flange mid-surface.
    ``web``
        The web mid-surface.

    Returns
    -------
    Part
    """
    part = Part(name)
    with part:
        geo = part.model.geometry

        y_top = h / 2 + tf / 2
        y_bot = -(h / 2 + tf / 2)

        # Top flange: rectangle in XZ plane at y = y_top
        _build_rect_surface(
            geo,
            -bf / 2, y_top, 0,
            bf / 2,  y_top, 0,
            bf / 2,  y_top, length,
            -bf / 2, y_top, length,
            label="top_flange",
        )

        # Bottom flange: rectangle in XZ plane at y = y_bot
        _build_rect_surface(
            geo,
            -bf / 2, y_bot, 0,
            bf / 2,  y_bot, 0,
            bf / 2,  y_bot, length,
            -bf / 2, y_bot, length,
            label="bottom_flange",
        )

        # Web: rectangle in YZ plane at x = 0
        _build_rect_surface(
            geo,
            0, -h / 2, 0,
            0,  h / 2, 0,
            0,  h / 2, length,
            0, -h / 2, length,
            label="web",
        )

        part.model.sync()
        apply_placement(anchor, align, length=length)

    return part

Profile sections

2D cross-sections for fiber analysis or sweep operations.

apeGmsh.sections.profile.W_profile

W_profile(bf: float, tf: float, h: float, tw: float, *, anchor='start', align='z', name: str = 'W_profile') -> Part

Create a W-shape 2D cross-section (no extrusion).

The I-shaped surface sits in the XY plane at z=0, centered on the origin.

Parameters

bf : float Flange width. tf : float Flange thickness. h : float Clear web height. tw : float Web thickness. name : str Part name.

Labels created

profile — the I-shaped surface.

Returns

Part

Example

::

section = W_profile(bf=150, tf=20, h=300, tw=10)
# section.has_file -> True (auto-persisted)
# Use for fiber analysis or sweep along a path
Source code in src/apeGmsh/sections/profile.py
def W_profile(
    bf: float,
    tf: float,
    h: float,
    tw: float,
    *,
    anchor="start",
    align="z",
    name: str = "W_profile",
) -> Part:
    """Create a W-shape 2D cross-section (no extrusion).

    The I-shaped surface sits in the XY plane at z=0, centered
    on the origin.

    Parameters
    ----------
    bf : float
        Flange width.
    tf : float
        Flange thickness.
    h : float
        Clear web height.
    tw : float
        Web thickness.
    name : str
        Part name.

    Labels created
    --------------
    ``profile`` — the I-shaped surface.

    Returns
    -------
    Part

    Example
    -------
    ::

        section = W_profile(bf=150, tf=20, h=300, tw=10)
        # section.has_file -> True (auto-persisted)
        # Use for fiber analysis or sweep along a path
    """
    part = Part(name)
    with part:
        geo = part.model.geometry
        boo = part.model.boolean

        total_h = 2 * tf + h
        outer  = geo.add_rectangle(x=-bf / 2, y=-total_h / 2, z=0, dx=bf, dy=total_h)
        void_l = geo.add_rectangle(x=-bf / 2, y=-h / 2, z=0, dx=bf / 2 - tw / 2, dy=h)
        void_r = geo.add_rectangle(x=tw / 2,  y=-h / 2, z=0, dx=bf / 2 - tw / 2, dy=h)
        boo.cut(outer, [void_l, void_r], dim=2)

        # Label the surviving surface
        import gmsh
        for _, tag in gmsh.model.getEntities(2):
            part.labels.add(2, [tag], name="profile")
            break

        # Profile has no extrusion length; only "start" and tuple
        # anchors apply.  Pass length=None — named modes other than
        # "start" raise (consistent with helper contract).
        apply_placement(anchor, align, length=None)

    return part