Curved Beam#

../../../../_images/curved_beam.png

Modelling a curved beam subjected to eccentric out-of-plane loading and evaluating its deflection:

  • Create a quarter-circle beam from an arc line with a rectangular cross-section

  • Fix one end fully and leave the other free

  • Apply an out-of-plane nodal force with an eccentricity of one radius, which twists the beam

  • Neglect self-weight in the load case

  • Determine the maximum total deflection of the curved beam

Keywords:
curved beam arc line nodal support nodal load force eccentricity torsion deflection
from dlubal.api import rfem, common
from math import inf, pi, cos, sin

# -------------------------------------------------------
# This example demonstrates how to model a quarter-circle
# beam with a rectangular cross-section which is loaded by
# means of an eccentric out-of-plane force.
# While neglecting self-weight, the maximum total
# deflection of the curved beam is retrieved.
# -------------------------------------------------------

# Editable parameters (SI units)
MODEL_NAME = "curved_beam"
MATERIAL = 'S235'
BEAM_RADIUS = 1.0                  # R [m]
CROSS_SECTION_WIDTH = 0.025        # b [m]
CROSS_SECTION_HEIGHT = 0.050       # h [m]
LOAD_FZ = 1000.0                   # F [N] = 1 kN, out of the beam's plane


def define_structure() -> list:
    """Define and return a list of structural objects."""

    return [
        rfem.structure_core.Material(
            no=1,
            name=MATERIAL,
        ),

        # Cross-Sections
        rfem.structure_core.CrossSection(
            no=1,
            material=1,
            type=rfem.structure_core.CrossSection.TYPE_PARAMETRIC_MASSIVE_I,
            b=CROSS_SECTION_WIDTH,
            h=CROSS_SECTION_HEIGHT,
        ),

        # Nodes
        rfem.structure_core.Node(
            no=1,
            coordinate_1=0.0,
            coordinate_2=0.0,
        ),
        rfem.structure_core.Node(
            no=2,
            coordinate_1=BEAM_RADIUS,
            coordinate_2=BEAM_RADIUS,
        ),

        # Lines
        # The arc control point is a third point ON the arc, at 135 deg. With the
        # ends at 180 deg and 90 deg it fixes a quarter circle of radius
        # BEAM_RADIUS centred on (BEAM_RADIUS, 0).
        rfem.structure_core.Line(
            no=1,
            type=rfem.structure_core.Line.TYPE_ARC,
            definition_nodes=[1, 2],
            arc_control_point=common.Vector3d(
                x=BEAM_RADIUS + BEAM_RADIUS*cos(3*pi/4),
                y=BEAM_RADIUS*sin(3*pi/4),
                z=0
            ),
        ),

        # Members
        rfem.structure_core.Member(
            no=1,
            line=1,
            cross_section_start=1,
            rotation_specification_type=rfem.structure_core.Member.ROTATION_SPECIFICATION_TYPE_INSIDE,
        ),

        # Nodal Supports
        # Fully fixed. Note that a support restrained in every direction is
        # invariant to the orientation of its axes, so there is no reason to
        # rotate them here.
        rfem.types_for_nodes.NodalSupport(
            no=1,
            nodes=[1],
            spring=common.Vector3d(x=inf, y=inf, z=inf),
            rotational_restraint=common.Vector3d(x=inf, y=inf, z=inf),
        ),
    ]

def define_loading() -> list:
    """Define and return a list of loading objects."""

    return [

        # Static Analysis Settings
        rfem.loading.StaticAnalysisSettings(
            no=1,
        ),

        # Load Cases
        rfem.loading.LoadCase(
            no=1,
            static_analysis_settings=1,
            self_weight_active=False,
        ),

        # Nodal Loads | LC1
        # The force acts out of the beam's plane, offset by one radius. That
        # eccentricity lands its line of action on the arc centre and is what
        # twists the beam - without it the member would only bend.
        rfem.loads.NodalLoad(
            no=1,
            load_type=rfem.loads.NodalLoad.LOAD_TYPE_COMPONENTS,
            nodes=[2],
            components_force=common.Vector3d(x=0, y=0, z=LOAD_FZ),
            load_case=1,
            force_eccentricity_enabled = True,
            force_eccentricity=common.Vector3d(x=0, y=-BEAM_RADIUS, z=0)
        ),
    ]

# Connect to the RFEM application
with rfem.Application() as rfem_app:

    app_info = rfem_app.get_application_info()
    print(f"\nApplication Info:\n{app_info}")

    # Modelling
    rfem_app.close_all_models(save_changes=False)
    rfem_app.create_model(name=MODEL_NAME)
    rfem_app.delete_all_objects()
    rfem_app.create_object_list(define_structure() + define_loading())

    # Calculation
    calculation_info = rfem_app.calculate_all(
        skip_warnings=True
    )
    print(f"\nCalculation Info:\n{calculation_info}")

    # Results
    member_deformation_df = rfem_app.get_results(
        results_type=rfem.results.STATIC_ANALYSIS_MEMBERS_LOCAL_DEFORMATIONS
    ).data

    if "u_abs" not in member_deformation_df.columns:
        raise RuntimeError(
            "Expected column 'u_abs' not found. "
            f"Available columns: {list(member_deformation_df.columns)}"
        )

    # Maximum total deflection.
    # u_abs is the resultant of the three components. For this model it equals
    # |u_z|, because a purely out-of-plane load leaves u_x and u_y at zero.
    max_u = member_deformation_df["u_abs"].abs().max()
    print(f"Max |u|: {max_u} m ({max_u * 1000:.2f} mm)")