Collar Beam Roof#

../../../../_images/collar_beam_roof.png

Modelling a collar roof subjected to 3 loads and evaluating the internal forces:

  • Create a 2D parametric model of collar beam roof

  • Connect members by hinges

  • Apply loads in separate load cases

  • Determine the maximum internal forces for ULS design situation

Keywords:
collar beam member hinge design situation internal forces ULS
from dlubal.api import rfem, common
from math import inf, sqrt

# -------------------------------------------------------
# This example demonstrates how to modelling a
# collar roof consists of two inclined beams which are
# connected by a hinge at the top and by pin supports at
# the bottom. A horizontal collar beam is connected to
# both beams by hinges. While neglecting
# self-weight, the maximum bending moment due to the
# ULS combination is retrieved.
# -------------------------------------------------------


# Editable parameters (SI units)

CROSS_SECTION_WIDTH = 6
CROSS_SECTION_HEIGHT = 18

SYSTEM_LENGTH = 12.0               # L  [m]
COLLAR_BEAM_LENGTH = 4.5           # b  [m]
SYSTEM_HEIGHT = 4.0                # H  [m]
HEIGHT_TO_COLLAR_BEAM = 2.5        # hu [m]
HEIGHT_FROM_COLLAR_BEAM = 1.5      # ho [m]

DISTRIBUTED_LOAD_RAFTER = 5000.0   # g  [N/m] = 5 kN/m
DISTRIBUTED_LOAD_COLLAR = 5000.0   # gk [N/m] = 5 kN/m
DISTRIBUTED_LOAD_WIND = 5000.0     # gw [N/m] = 5 kN/m



def define_structure() -> list:
    """Define and return structural model objects created only once."""
    half_span = SYSTEM_LENGTH / 2.0
    apex_x = half_span
    apex_z = -SYSTEM_HEIGHT

    left_rafter_rel = HEIGHT_TO_COLLAR_BEAM / SYSTEM_HEIGHT
    right_rafter_rel = HEIGHT_FROM_COLLAR_BEAM / SYSTEM_HEIGHT

    rafter_length = sqrt(half_span ** 2 + SYSTEM_HEIGHT ** 2)
    left_rafter_abs = left_rafter_rel * rafter_length
    right_rafter_abs = right_rafter_rel * rafter_length

    return [
        rfem.structure_core.Material(
            no=1,
            name="C24",
        ),
        rfem.structure_core.CrossSection(
            no=1,
            type=rfem.structure_core.CrossSection.TYPE_STANDARDIZED_TIMBER,
            material=1,
            b=CROSS_SECTION_WIDTH,
            h=CROSS_SECTION_HEIGHT,
            shear_stiffness_deactivated=True,
        ),

        # Main truss nodes
        rfem.structure_core.Node(no=1),
        rfem.structure_core.Node(no=2, coordinate_1=SYSTEM_LENGTH),
        rfem.structure_core.Node(no=3, coordinate_1=apex_x, coordinate_3=apex_z),

        # Collar beam nodes as points on rafters
        rfem.structure_core.Node(
            no=6,
            type=rfem.structure_core.Node.TYPE_ON_MEMBER,
            on_member_reference_member=1,
            distance_from_start_relative=left_rafter_rel,
            distance_from_start_absolute=left_rafter_abs,
        ),
        rfem.structure_core.Node(
            no=7,
            type=rfem.structure_core.Node.TYPE_ON_MEMBER,
            on_member_reference_member=2,
            distance_from_start_relative=right_rafter_rel,
            distance_from_start_absolute=right_rafter_abs,
        ),

        # Truss lines
        rfem.structure_core.Line(no=1, definition_nodes=[1, 3]),
        rfem.structure_core.Line(no=2, definition_nodes=[3, 2]),
        rfem.structure_core.Line(no=4, definition_nodes=[6, 7]),

        # Members
        rfem.structure_core.Member(no=1, line=1, cross_section_start=1, member_hinge_end=1),
        rfem.structure_core.Member(no=2, line=2, cross_section_start=1),
        rfem.structure_core.Member(no=3, line=4, cross_section_start=1, member_hinge_start=1, member_hinge_end=1),

        # Supports and hinge
        rfem.types_for_nodes.NodalSupport(
            no=1,
            user_defined_name_enabled=True,
            name="Gelenkig",
            nodes=[1, 2],
            spring=common.Vector3d(x=inf, y=0, z=inf),
        ),
        rfem.types_for_members.MemberHinge(
            no=1,
            axial_release_n=inf,
            axial_release_vz=inf,
            moment_release_my=0,
        ),
    ]

def define_loading() -> list:
    """Define separate load cases acting on one shared collar-roof structure."""

    return [
        rfem.loading.LoadCase(
            no=1,
            name="Distributed load rafter (g)",
            static_analysis_settings=1,
            self_weight_active=False,
        ),
        rfem.loading.LoadCase(
            no=2,
            name="Distributed load collar beam (gk)",
            static_analysis_settings=1,
            self_weight_active=False,
        ),
        rfem.loading.LoadCase(
            no=3,
            name="Distributed load wind (gw)",
            static_analysis_settings=1,
            self_weight_active=False,
        ),
        rfem.loads.MemberLoad(
            no=1,
            members=[1, 2],
            load_case=1,
            load_direction=rfem.loads.MemberLoad.LOAD_DIRECTION_GLOBAL_Z_OR_USER_DEFINED_W_PROJECTED_LENGTH,
            magnitude=DISTRIBUTED_LOAD_RAFTER,
        ),
        rfem.loads.MemberLoad(
            no=2,
            members=[3],
            load_case=2,
            magnitude=DISTRIBUTED_LOAD_COLLAR,
        ),
        rfem.loads.MemberLoad(
            no=3,
            members=[1],
            load_case=3,
            coordinate_system=common.CoordinateSystemRepresentation(
                type=common.CoordinateSystemRepresentation.COORDINATE_SYSTEM_TYPE_LOCAL
            ),
            magnitude=DISTRIBUTED_LOAD_WIND,
        ),
        rfem.loading.StaticAnalysisSettings(
            no=1
        ),
        rfem.loading.CombinationWizard(
            no=1,
            static_analysis_settings=1
        ),
        rfem.loading.DesignSituation(
            no=1,
            name="ULS (STR/GEO) - Permanent and transient - Eq. 6.10",
            design_situation_type=rfem.loading.DesignSituation.DESIGN_SITUATION_TYPE_STR_PERMANENT_AND_TRANSIENT_6_10,
            combination_wizard=1,
        )
    ]


with rfem.Application() as rfem_app:

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

    # Modelling
    rfem_app.create_model(name='collar_beam_roof')

    base_data = rfem_app.get_base_data()
    base_data.combinations_settings.combination_wizard_active = True
    base_data.main.model_type = rfem.BaseData.Main.MODEL_TYPE_2D_XZ_PLANE_STRESS
    rfem_app.set_base_data(base_data=base_data)

    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_internal_forces_df = rfem_app.get_results(
        results_type=rfem.results.STATIC_ANALYSIS_MEMBERS_INTERNAL_FORCES,
    ).data.copy()

    idx_max_abs_m_y = member_internal_forces_df["m_y"].abs().idxmax()
    row = member_internal_forces_df.loc[idx_max_abs_m_y]

    print(f"Max |m_y|:\n{row}")