Effective Lengths#

../../../../../_images/steel_design_effective_lengths.png

This example demonstrates the stability design of a steel column using the equivalent member method according to EN 1993 as follows:

  • Model the steel column with appropriate supports.

  • Apply compressive axial and lateral forces.

  • Define steel design configuration.

  • Define effective lengths using manually defined nodal supports.

  • Perform the calculation and steel design check.

  • Retrieve results for buckling resistance and critical loading.

  • Extract specific values from the design check details of stability check.

from dlubal.api import rstab, common
from math import inf
import pandas

# -------------------------------------------------------
# This example demonstrates the stability analysis of a steel column
# using the equivalent member method, in accordance with DIN EN 1993-1-3:2020-11.
# It includes the definition of effective lengths and the extraction of detailed results
# related to buckling resistance and critical loading.
# -------------------------------------------------------


def define_structure_objects() -> list:

    # The column is designed as a simply supported beam in the z-direction.
    # It is laterally supported in the y-direction at one-third of the column height.
    # In addition, rotation about the x-axis is prevented in the column center.
    # The cross-section consists of two C-sections arranged back-to-back and connected by pairs of bolts in the web area.

    return [

        # Materials
        rstab.structure_core.Material(
            no=1,
            user_defined_name_enabled=False,
            name="S350GD 1.0529 | EN 10346:2015-10",
        ),

        # Cross-Sections
        rstab.structure_core.CrossSection(
            no=1,
            type=rstab.structure_core.CrossSection.TYPE_PARAMETRIC_THIN_WALLED,
            parametrization_type=rstab.structure_core.CrossSection.PARAMETRIZATION_TYPE_PARAMETRIC_THIN_WALLED__2_C_SECTIONS__2C,
            name="2C 0.25/0.08/0.0025/0.005/0.04/0/0.0025/C",
            material=1,
        ),

        # Nodes
        rstab.structure_core.Node(
            no=1,
        ),
        rstab.structure_core.Node(
            no=2,
            coordinate_3=-8,
        ),
        rstab.structure_core.Node(
            no=3,
            type=rstab.structure_core.Node.TYPE_ON_MEMBER,
            on_member_reference_member=1,
            distance_from_start_relative=0.25,
            distance_from_start_absolute=2,
        ),
        rstab.structure_core.Node(
            no=4,
            type=rstab.structure_core.Node.TYPE_ON_MEMBER,
            on_member_reference_member=1,
            distance_from_start_absolute=4,
        ),
        rstab.structure_core.Node(
            no=5,
            type=rstab.structure_core.Node.TYPE_ON_MEMBER,
            on_member_reference_member=1,
            distance_from_start_relative=0.75,
            distance_from_start_absolute=6,
        ),

        # Member
        rstab.structure_core.Member(
            no=1,
            node_start = 1,
            node_end = 2,
            cross_section_start=1,
        ),

        # Nodal Supports
        rstab.types_for_nodes.NodalSupport(
            no=1,
            user_defined_name_enabled=True,
            name="Gelenkig",
            nodes=[1],
            spring=common.Vector3d(x=inf, y=inf, z=inf),
            rotational_restraint=common.Vector3d(x=0, y=0, z=inf),
        ),
        rstab.types_for_nodes.NodalSupport(
            no=2,
            nodes=[2],
            spring=common.Vector3d(x=inf, y=inf, z=0),
            rotational_restraint=common.Vector3d(x=0, y=0, z=inf),
        ),
        rstab.types_for_nodes.NodalSupport(
            no=3,
            nodes=[3, 5],
            spring=common.Vector3d(x=0, y=inf, z=0),
        ),
        rstab.types_for_nodes.NodalSupport(
            no=4,
            nodes=[4],
            spring=common.Vector3d(x=0, y=inf, z=0),
            rotational_restraint=common.Vector3d(x=0, y=0, z=inf),
        )
    ]


def define_loading_objects() -> list:

    # The column is subjected to an axial compressive force and and three lateral loads.

    return [

        # Load Cases
        rstab.loading.LoadCase(
            no=1,
            name="Design Load",
            static_analysis_settings=1,
            self_weight_active=False,
        ),

        # Design Situations
        rstab.loading.DesignSituation(
            no=1,
            user_defined_name_enabled = True,
            name="ULS - Permanent and transient",
            design_situation_type=rstab.loading.DesignSituation.DESIGN_SITUATION_TYPE_STR_PERMANENT_AND_TRANSIENT_6_10,
        ),

        # Load Combinations
        rstab.loading.LoadCombination(
            no=1,
            design_situation=1,
            name="LC1",
            static_analysis_settings=1,
            combination_rule_str="LC1",
        ),

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

        # Nodal Loads | LC1
        rstab.loads.NodalLoad(
            no=1,
            nodes=[2],
            force_magnitude=40000,
            load_direction=rstab.loads.NodalLoad.LOAD_DIRECTION_GLOBAL_Z_OR_USER_DEFINED_W_TRUE_LENGTH,
            load_case=1,
        ),

        # Member Loads | LC1
        rstab.loads.MemberLoad(
            no=1,
            members=[1],
            load_case=1,
            load_distribution=rstab.loads.MemberLoad.LOAD_DISTRIBUTION_CONCENTRATED_N,
            load_direction=rstab.loads.MemberLoad.LOAD_DIRECTION_GLOBAL_X_OR_USER_DEFINED_U_TRUE_LENGTH,
            magnitude=8000,
            distance_a_absolute=2,
            distance_b_absolute=2,
            count_n=3,
        )
    ]


def define_steel_design_objects() -> list:

    return [
        # Steel Design Configurations
        rstab.steel_design_objects.SteelDesignUlsConfiguration(
            no=1,
            assigned_to_all_members=True,
        ),
        rstab.steel_design_objects.SteelDesignSlsConfiguration(
            no=1,
            assigned_to_all_members=True,
        ),

        # Design Supports
        rstab.types_for_members.DesignSupport(
            no=1,
            type=rstab.types_for_members.DesignSupport.TYPE_STEEL,
            user_defined_name_enabled=True,
            name="Zwischenlager",
            assigned_to_members=[1],
            assigned_to_nodes=[3, 4, 5],
            consider_in_deflection_design_y=False,
            consider_in_deflection_design_z=False,
            design_support_orientation_z=rstab.types_for_members.DesignSupport.DESIGN_SUPPORT_ORIENTATION_Z_BOTH,
            support_width_z=0.064,
        ),

        # Steel Effective Lengths
        rstab.steel_design.SteelEffectiveLengths(
            no=1,
            members=[1],
            flexural_buckling_about_y = True,
            flexural_buckling_about_z = True,
            torsional_buckling = True,
            lateral_torsional_buckling = True,
            principal_section_axes = True,
            geometric_section_axes = False,
            intermediate_nodes = True,

            nodal_supports = rstab.steel_design.SteelEffectiveLengths.NodalSupportsTable(
                rows = [
                    rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow(
                        no = 1,
                        nodes=[1],
                        support_type = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.SUPPORT_TYPE_FIXED_IN_Z_Y_AND_TORSION,
                        support_in_z = True,
                        eccentricity_type = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.ECCENTRICITY_TYPE_NONE,
                        support_in_y = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.SUPPORT_IN_Y_SUPPORT_STATUS_YES,
                        restraint_about_x = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.RESTRAINT_ABOUT_X_SUPPORT_STATUS_YES,
                        restraint_about_z = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.RESTRAINT_ABOUT_Z_SUPPORT_STATUS_NO,
                        restraint_warping = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.RESTRAINT_WARPING_SUPPORT_STATUS_NO,
                    ),
                    rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow(
                        no = 2,
                        nodes=[3],
                        support_type = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.SUPPORT_TYPE_FIXED_IN_Y,
                        support_in_z = False,
                        eccentricity_type = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.ECCENTRICITY_TYPE_NONE,
                        support_in_y = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.SUPPORT_IN_Y_SUPPORT_STATUS_YES,
                        restraint_about_x = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.RESTRAINT_ABOUT_X_SUPPORT_STATUS_NO,
                        restraint_about_z = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.RESTRAINT_ABOUT_Z_SUPPORT_STATUS_NO,
                        restraint_warping = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.RESTRAINT_WARPING_SUPPORT_STATUS_NO,
                    ),
                    rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow(
                        no = 3,
                        nodes=[4],
                        support_type = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.SUPPORT_TYPE_INDIVIDUALLY,
                        support_in_z = False,
                        eccentricity_type = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.ECCENTRICITY_TYPE_NONE,
                        support_in_y = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.SUPPORT_IN_Y_SUPPORT_STATUS_YES,
                        restraint_about_x = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.RESTRAINT_ABOUT_X_SUPPORT_STATUS_YES,
                        restraint_about_z = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.RESTRAINT_ABOUT_Z_SUPPORT_STATUS_NO,
                        restraint_warping = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.RESTRAINT_WARPING_SUPPORT_STATUS_NO,
                    ),
                    rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow(
                        no = 4,
                        nodes=[5],
                        support_type = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.SUPPORT_TYPE_FIXED_IN_Y,
                        support_in_z = False,
                        eccentricity_type = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.ECCENTRICITY_TYPE_NONE,
                        support_in_y = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.SUPPORT_IN_Y_SUPPORT_STATUS_YES,
                        restraint_about_x = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.RESTRAINT_ABOUT_X_SUPPORT_STATUS_NO,
                        restraint_about_z = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.RESTRAINT_ABOUT_Z_SUPPORT_STATUS_NO,
                        restraint_warping = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.RESTRAINT_WARPING_SUPPORT_STATUS_NO,
                    ),
                    rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow(
                        no = 5,
                        nodes=[2],
                        support_type = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.SUPPORT_TYPE_FIXED_IN_Z_Y_AND_TORSION,
                        support_in_z = True,
                        eccentricity_type = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.ECCENTRICITY_TYPE_NONE,
                        support_in_y = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.SUPPORT_IN_Y_SUPPORT_STATUS_YES,
                        restraint_about_x = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.RESTRAINT_ABOUT_X_SUPPORT_STATUS_YES,
                        restraint_about_z = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.RESTRAINT_ABOUT_Z_SUPPORT_STATUS_NO,
                        restraint_warping = rstab.steel_design.SteelEffectiveLengths.NodalSupportsRow.RESTRAINT_WARPING_SUPPORT_STATUS_NO,
                    ),
                ]
            ),

            factors = rstab.steel_design.SteelEffectiveLengths.FactorsTable(
                rows = [
                    rstab.steel_design.SteelEffectiveLengths.FactorsRow(
                        flexural_buckling_u = 1,
                        flexural_buckling_v = 1,
                        torsional_buckling = 1,
                    ),
                    rstab.steel_design.SteelEffectiveLengths.FactorsRow(
                        flexural_buckling_v = 1,
                    ),
                    rstab.steel_design.SteelEffectiveLengths.FactorsRow(
                        flexural_buckling_v = 1,
                        torsional_buckling = 1,
                    ),
                    rstab.steel_design.SteelEffectiveLengths.FactorsRow(
                        flexural_buckling_v = 1,
                    ),
                ]
            ),
            different_properties = True,
            factors_definition_absolute = False,
            import_from_stability_analysis_enabled = False,
            determination_mcr_europe = rstab.steel_design.SteelEffectiveLengths.DeterminationMcrEurope.DETERMINATION_MCR_EUROPE_EIGENVALUE,
        ),
    ]


def get_design_check_details_id(design_checks_df: pandas.DataFrame, check_type: str) -> int:
    """
    This function filters the design checks DataFrame by the specified 'design_check_type'
    and returns the 'design_check_details_id' corresponding to the row with the highest 'design_ratio'.
    """
    # Filter the DataFrame based on 'design_check_type'
    filtered_rows = design_checks_df[design_checks_df['design_check_type'] == check_type]

    # Find the row with the maximum 'design_ratio'
    max_row = filtered_rows.loc[filtered_rows['design_ratio'].idxmax()]

    # Return the 'design_check_details_id' for that row
    return max_row['design_check_details_id']


def get_design_check_value_by_key(design_check_details_df, key) -> str:
    """
    This function extracts the 'value', 'unit', and 'caption' from the design check details
    based on the specified 'key'.
    """
    row = design_check_details_df.loc[design_check_details_df['key'] == key]

    if row.empty:
        raise ValueError(f"Key '{key}' not found in design check details.")

    caption = row['caption'].values[0]
    key = row['key'].values[0]
    value = row['value'].values[0]
    unit = row['unit'].values[0]

    return f"{key} = {value} [{unit}]\t| {caption}"


# Connect to the RSTAB application
with rstab.Application() as rstab_app:

    # Initialize model
    rstab_app.close_all_models(save_changes=False)
    rstab_app.create_model(name="steel_design_effective_lengths.rf6")

    # Edit base data
    base_data = rstab_app.get_base_data()
    base_data.addons.steel_design_active = True
    base_data.standards.steel_design_standard = rstab.BaseData.Standards.STEEL_DESIGN_NATIONAL_ANNEX_AND_EDITION_EN_1993_DIN_2020_11_STANDARD
    rstab_app.set_base_data(base_data=base_data)
    rstab_app.delete_all_objects()

    # Create model objects
    rstab_app.create_object_list(
        objs=
            define_structure_objects()+
            define_loading_objects()+
            define_steel_design_objects()
    )

    # Calculate model
    rstab_app.generate_combinations()
    calculation_info = rstab_app.calculate_all(
        skip_warnings=False
    )

    # Retrieve design check ratios
    design_checks_df = rstab_app.get_results(
        results_type=rstab.results.STEEL_DESIGN_MEMBERS_DESIGN_RATIOS,
    ).data
    print(f"\nDesign Check Ratios:\n {design_checks_df}")

    # Retrieve design check details
    design_check_type = "ST3310.00" # Stability | Bending and compression
    design_check_desc = design_checks_df.loc[design_checks_df['design_check_type'] == design_check_type, 'design_check_description'].values[0]
    design_check_details_id = get_design_check_details_id(
        design_checks_df=design_checks_df,
        check_type=design_check_type
    )
    design_check_details_df = rstab_app.get_results(
        results_type=rstab.results.STEEL_DESIGN_DESIGN_CHECK_DETAILS,
        filters=[
            rstab.results.ResultsFilter(
                column_id="design_check_details_id",
                filter_expression=str(design_check_details_id)
            )
        ],
    ).data
    print(f"\nDesign Check Details | {design_check_type} | {design_check_desc}:\n {design_check_details_df}")

    # Extract specific data from the design details for the selected key
    print(f"\nDesign Check Values | {design_check_type} | {design_check_desc}:")
    print(get_design_check_value_by_key(design_check_details_df, key='n_c_ed'))
    print(get_design_check_value_by_key(design_check_details_df, key='m_y_ed'))
    print(get_design_check_value_by_key(design_check_details_df, key='a_eff'))
    print(get_design_check_value_by_key(design_check_details_df, key='n_cr_y'))
    print(get_design_check_value_by_key(design_check_details_df, key='lambdaand_773_y'))
    print(get_design_check_value_by_key(design_check_details_df, key='m_cr'))
    print(get_design_check_value_by_key(design_check_details_df, key='lambdaand_773_lt'))
    print(get_design_check_value_by_key(design_check_details_df, key='n_b_rd'))
    print(get_design_check_value_by_key(design_check_details_df, key='m_b_rd'))