Member Reinforcement#

../../../../../_images/concrete_design_member_reinforcement.png

This example demonstrates how to model provided longitudinal and shear reinforcement for a single-span member with cantilever and review the results of bending design check according to EN 1992:

  • Model the single-span concrete member with cantilever.

  • Define the provided longitudinal and shear reinforcement.

  • Configure the concrete design settings and supports.

  • Run the static analysis and concrete design check.

  • Review the bending resistance results for the top and bottom reinforcement.

from dlubal.api import rfem, common
from math import inf
import pandas
from enum import Enum
import re

# -------------------------------------------------------
# This example demonstrates the ultimate limit state design check of a concrete
# single-span member with cantilever in accordance with DIN EN 1992-1-1:NA 2015-12.
# It includes the definition of shear and longitudal reinforacement and the extraction
# of detailed results related to Section resistance for bending with or without axial force.
# -------------------------------------------------------


# Editable parameters (SI units)
LENGTH_TOTAL = 8.0
LENGHT_CANTILEVER = 2.0

CONCRETE_GRADE = "C30/37"
STEEL_REINF_GRADE = "B500S(A)"
CROSS_SECTION = "R_M1 0.3/0.45"     # rectangle 300/450



def define_structure() -> list:

    # Reinforced concrete design of single-span continuous beam with tapered cantilever.
    # Because the model is defined in a 2D (XZ plane) stress plane, it is supported against translational motion.

    return [

        # Materials
        rfem.structure_core.Material(
            no=1,
            name="C25/30",
        ),
        rfem.structure_core.Material(
            no=2,
            name="B500S(A)",
        ),

        # Cross-Sections
        rfem.structure_core.CrossSection(
            no=1,
            name="R_M1 0.3/0.45",  # rectangle 300/450
            material=1,
        ),

        # Nodes
        rfem.structure_core.Node(
            no=1,
            coordinate_1=0
        ),
        rfem.structure_core.Node(
            no=2,
            type=rfem.structure_core.Node.TYPE_ON_MEMBER,
            on_member_reference_member=1,
            distance_from_start_is_defined_as_relative=False,
            distance_from_start_absolute=LENGTH_TOTAL-LENGHT_CANTILEVER,
        ),
        rfem.structure_core.Node(
            no=3,
            coordinate_1=LENGTH_TOTAL,
        ),


        # Line
        rfem.structure_core.Line(
            no=1,
            definition_nodes=[1, 3],
        ),

        # Member
        rfem.structure_core.Member(
            no=1,
            line=1,
            cross_section_start=1,
            concrete_cover_different_at_cross_section_sides_enabled=True,
            concrete_durability_top=1,
            concrete_durability_left=2,
            concrete_durability_right=2,
            concrete_durability_bottom=2,
            concrete_shear_reinforcement_spans = rfem.structure_core.Member.ConcreteShearReinforcementSpansTable(
                rows = [
                    rfem.structure_core.Member.ConcreteShearReinforcementSpansRow(
                        stirrup_type = rfem.structure_core.Member.ConcreteShearReinforcementSpansRow.STIRRUP_TYPE_TWO_LEGGED_CLOSED_HOOK_135,
                        stirrup_diameter = 0.008,
                        stirrup_distances = 0.3,
                        span_position_definition_format=rfem.structure_core.Member.ConcreteShearReinforcementSpansRow.SPAN_POSITION_DEFINITION_FORMAT_ABSOLUTE,
                        span_start_absolute = 0,
                        span_end_absolute = (LENGTH_TOTAL-LENGHT_CANTILEVER)*0.75,
                        stirrup_layout_rule = rfem.structure_core.Member.ConcreteShearReinforcementSpansRow.STIRRUP_LAYOUT_RULE_START_EQUALS_END,
                    ),
                    rfem.structure_core.Member.ConcreteShearReinforcementSpansRow(
                        stirrup_type = rfem.structure_core.Member.ConcreteShearReinforcementSpansRow.STIRRUP_TYPE_TWO_LEGGED_CLOSED_HOOK_135,
                        stirrup_diameter = 0.008,
                        stirrup_distances = 0.2,
                        span_position_definition_format=rfem.structure_core.Member.ConcreteShearReinforcementSpansRow.SPAN_POSITION_DEFINITION_FORMAT_ABSOLUTE,
                        span_start_absolute = (LENGTH_TOTAL-LENGHT_CANTILEVER)*0.75,
                        span_end_absolute = LENGTH_TOTAL,
                        stirrup_layout_rule = rfem.structure_core.Member.ConcreteShearReinforcementSpansRow.STIRRUP_LAYOUT_RULE_START_EQUALS_END,
                    ),
                ],
            ),
            concrete_longitudinal_reinforcement_items = rfem.structure_core.Member.ConcreteLongitudinalReinforcementItemsTable(
                rows = [
                    rfem.structure_core.Member.ConcreteLongitudinalReinforcementItemsRow(
                        # name = "2Ø12 | 1Ø12 | 3Ø16",
                        rebar_type = rfem.structure_core.Member.ConcreteLongitudinalReinforcementItemsRow.REBAR_TYPE_UNSYMMETRICAL,
                        material=2,
                        bar_count_unsymmetrical_top_side=2,
                        bar_diameter_unsymmetrical_top_side=0.012,
                        bar_count_unsymmetrical_at_side=1,
                        bar_diameter_unsymmetrical_at_side=0.010,
                        bar_count_unsymmetrical_bottom_side=3,
                        bar_diameter_unsymmetrical_bottom_side=0.016,
                        span_position_definition_format=rfem.structure_core.Member.ConcreteLongitudinalReinforcementItemsRow.SPAN_POSITION_DEFINITION_FORMAT_ABSOLUTE,
                        span_start_absolute = 0,
                        span_end_absolute = LENGTH_TOTAL,
                    ),
                    rfem.structure_core.Member.ConcreteLongitudinalReinforcementItemsRow(
                        # name = " -- | -- | 2Ø16",
                        rebar_type = rfem.structure_core.Member.ConcreteLongitudinalReinforcementItemsRow.REBAR_TYPE_UNSYMMETRICAL,
                        material=2,
                        bar_count_unsymmetrical_top_side=0,
                        bar_count_unsymmetrical_at_side=0,
                        bar_count_unsymmetrical_bottom_side=2,
                        bar_diameter_unsymmetrical_bottom_side=0.016,
                        span_position_definition_format=rfem.structure_core.Member.ConcreteLongitudinalReinforcementItemsRow.SPAN_POSITION_DEFINITION_FORMAT_ABSOLUTE,
                        span_start_absolute = 0,
                        span_end_absolute = LENGTH_TOTAL-LENGHT_CANTILEVER,
                        additional_offset_type=rfem.structure_core.Member.ConcreteLongitudinalReinforcementItemsRow.ADDITIONAL_OFFSET_TYPE_FROM_STIRRUP,
                        additional_offset_left_side=0.04,
                        additional_offset_right_side=0.04,
                    ),
                    rfem.structure_core.Member.ConcreteLongitudinalReinforcementItemsRow(
                        # name = "2Ø12 | -- | -- ",
                        rebar_type = rfem.structure_core.Member.ConcreteLongitudinalReinforcementItemsRow.REBAR_TYPE_LINE,
                        material=2,
                        bar_count_line=2,
                        bar_diameter_line=0.012,
                        additional_offset_type=rfem.structure_core.Member.ConcreteLongitudinalReinforcementItemsRow.ADDITIONAL_OFFSET_TYPE_FROM_STIRRUP,
                        additional_offset_reference_type_at_start=rfem.structure_core.Member.ConcreteLongitudinalReinforcementItemsRow.ADDITIONAL_OFFSET_REFERENCE_TYPE_AT_START_LEFT_TOP,
                        additional_horizontal_offset_at_start=0.04,
                        additional_vertical_offset_at_start=0.0,
                        additional_offset_reference_type_at_end=rfem.structure_core.Member.ConcreteLongitudinalReinforcementItemsRow.ADDITIONAL_OFFSET_REFERENCE_TYPE_AT_START_RIGHT_TOP,
                        additional_horizontal_offset_at_end=0.04,
                        additional_vertical_offset_at_end=0.0,
                        span_position_definition_format=rfem.structure_core.Member.ConcreteLongitudinalReinforcementItemsRow.SPAN_POSITION_DEFINITION_FORMAT_ABSOLUTE,
                        span_start_absolute = LENGTH_TOTAL-LENGHT_CANTILEVER*1.6,
                        span_end_absolute = LENGTH_TOTAL-LENGHT_CANTILEVER*0.4,
                    ),
                ]
            ),
        ),

        # Concrete durability
        rfem.reinforcement.ConcreteDurability( # XC1/XF2
            no=1,
            corrosion_induced_by_carbonation_enabled = True,
            corrosion_induced_by_carbonation = rfem.reinforcement.ConcreteDurability.CORROSION_INDUCED_BY_CARBONATION_DRY_OR_PERMANENTLY_WET,
            freeze_thaw_attack_enabled = True,
            freeze_thaw_attack = rfem.reinforcement.ConcreteDurability.FREEZE_THAW_ATTACK_MODERATE_WATER_SATURATION_DEICING,
            allowance_of_deviation_type = rfem.reinforcement.ConcreteDurability.ALLOWANCE_OF_DEVIATION_TYPE_STANDARD,
        ),

        rfem.reinforcement.ConcreteDurability( # XC3/XF2
            no=2,
            corrosion_induced_by_carbonation_enabled = True,
            corrosion_induced_by_carbonation = rfem.reinforcement.ConcreteDurability.CORROSION_INDUCED_BY_CARBONATION_MODERATE_HUMIDITY,
            freeze_thaw_attack_enabled = True,
            freeze_thaw_attack = rfem.reinforcement.ConcreteDurability.FREEZE_THAW_ATTACK_MODERATE_WATER_SATURATION_DEICING,
            allowance_of_deviation_type = rfem.reinforcement.ConcreteDurability.ALLOWANCE_OF_DEVIATION_TYPE_STANDARD,
        ),

        # Nodal Supports
        rfem.types_for_nodes.NodalSupport(
            no=1,
            user_defined_name_enabled=True,
            name="Hinged",
            nodes=[1],
            spring=common.Vector3d(x=inf, y=inf, z=inf),
            rotational_restraint=common.Vector3d(x=inf, y=0, z=inf),
        ),
        rfem.types_for_nodes.NodalSupport(
            no=2,
            user_defined_name_enabled=True,
            name="Moveable in X",
            nodes=[2],
            spring=common.Vector3d(x=0, y=inf, z=inf),
            rotational_restraint=common.Vector3d(x=0, y=0, z=inf),
        ),

    ]


def define_loading() -> list:

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

    return [

        # Load Cases
        rfem.loading.LoadCase(
            no=1,
            name="Self-weight",
            static_analysis_settings=1,
            self_weight_active=True,
        ),
        rfem.loading.LoadCase(
            no=2,
            name="Variable Load",
            static_analysis_settings=1,
            action_category=rfem.loading.Action.IMPOSED_LOAD_CATEGORY_IMPOSED_LOADS_CATEGORY_A,
        ),

        # Loads
        rfem.loads.MemberLoad(
            no=1,
            load_case=1,
            members=[1],
            load_distribution=rfem.loads.MemberLoad.LOAD_DISTRIBUTION_UNIFORM,
            magnitude=10000,
        ),
        rfem.loads.MemberLoad(
            no=2,
            load_case=2,
            members=[1],
            load_distribution=rfem.loads.MemberLoad.LOAD_DISTRIBUTION_UNIFORM,
            magnitude=15000,
        ),

        # Design Situations
        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
        ),

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

        rfem.loading.CombinationWizard(
            no=1,
            static_analysis_settings=1,
        ),

    ]


def define_concrete_design() -> list:

    return [
        # Concrete Design Configurations
        rfem.concrete_design_objects.ConcreteDesignUlsConfiguration(
            no=1,
            assigned_to_all_members=True,
            assigned_to_all_nodes=True,
        ),

        # Design Supports
        rfem.types_for_members.DesignSupport(
            no=1,
            type=rfem.types_for_members.DesignSupport.TYPE_CONCRETE,
            assigned_to_members=[1],
            assigned_to_nodes=[1],
            direct_support_z_enabled=True,
            inner_support_z_enabled=False,
            support_width_z=0.4,
            consider_in_deflection_design_z=True,
            consider_in_deflection_design_y=False,
        ),
        rfem.types_for_members.DesignSupport(
            no=2,
            type=rfem.types_for_members.DesignSupport.TYPE_CONCRETE,
            assigned_to_members=[1],
            assigned_to_nodes=[2],
            direct_support_z_enabled=True,
            inner_support_z_enabled=True,
            concrete_ratio_of_moment_redistribution_z=0.850,
            support_width_z=0.4,
            consider_in_deflection_design_z=True,
            consider_in_deflection_design_y=False,
        ),
    ]


class ReinforcementLayer(Enum):
    TOP = 0
    BOTTOM = 1

def get_max_req_reinf_location(required_reinf_df: pandas.DataFrame, reinforcement_layer: "ReinforcementLayer") -> float:
    """
    Returns the design_check_details_id for the row with the maximum longitudinal reinforcement area
    at the specified reinforcement layer (ReinforcementLayer.TOP or ReinforcementLayer.BOTTOM).

    Args:
        required_reinf_df (pandas.DataFrame): DataFrame with required reinforcement data.
        reinforcement_layer (ReinforcementLayer): Enum value ReinforcementLayer.TOP or ReinforcementLayer.BOTTOM.

    Returns:
        float: location for the row with the maximum reinforcement area.
    """
    if not isinstance(reinforcement_layer, ReinforcementLayer):
        raise ValueError("reinforcement_layer must be an instance of ReinforcementLayer Enum")

    layer_map = {ReinforcementLayer.TOP: "top", ReinforcementLayer.BOTTOM: "bottom"}
    col = f"longitudinal_reinforcement_area_a_s_{layer_map[reinforcement_layer]}"
    if col not in required_reinf_df.columns:
        raise ValueError(f"Column '{col}' not found in DataFrame.")

    max_row = required_reinf_df.loc[required_reinf_df[col].idxmax()]
    return max_row["location"]


def get_design_check_details_id_for_location(design_checks_df: pandas.DataFrame, location: float):
    """
    Returns the design_check_details_id for the row at the specified location
    with the maximum top longitudinal reinforcement area in design_checks_df.

    Args:
        design_checks_df (pandas.DataFrame): DataFrame with design check results.
        location: Value to filter the 'location_x' column (float or int).

    Returns:
        int: design_check_details_id for the row with the maximum top reinforcement area at the given location.
    """

    filtered = design_checks_df[design_checks_df["location_x"] == location]
    if filtered.empty:
        raise ValueError(f"No rows found for location_x == {location}")

    max_row = filtered.loc[filtered["design_ratio"].idxmax()]
    return max_row["design_check_details_id"]


def get_design_check_value_by_key(design_check_details, key) -> str:
    """
    This function extracts the 'value', 'unit', and 'caption' from the design check details
    based on the specified 'key'. The unit string is cleaned to remove any HTML tags.
    """
    row = design_check_details.loc[design_check_details['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]

    # Remove HTML tags from unit string
    unit_clean = re.sub(r"<[^>]+>", "", str(unit))

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


# -------------------------------------------------------
# MAIN SCRIPT
# -------------------------------------------------------

with rfem.Application() as rfem_app:

    # Initialize model
    # rfem_app.close_all_models(save_changes=False)
    rfem_app.create_model(name="concrete_design_member_reinf.rf6")

    # Edit base data
    base_data = rfem_app.get_base_data()
    base_data.combinations_settings.combination_wizard_active = True
    base_data.addons.concrete_design_active = True
    base_data.addons.load_wizards_active = True
    base_data.addons.combination_wizard_and_classification_active = True
    base_data.standards.concrete_design_standard = rfem.BaseData.Standards.CONCRETE_DESIGN_NATIONAL_ANNEX_AND_EDITION_EN_1992_DIN_2015_12_STANDARD
    base_data.standards.load_wizard_standard = rfem.BaseData.Standards.LOAD_WIZARD_NATIONAL_ANNEX_AND_EDITION_EN_1991_DIN_2019_04_STANDARD
    base_data.standards.combination_wizard_standard = rfem.BaseData.Standards.COMBINATION_WIZARD_NATIONAL_ANNEX_AND_EDITION_EN_1990_DIN_2012_08_STANDARD
    base_data.main.model_type = rfem.BaseData.Main.MODEL_TYPE_2D_XZ_PLANE_STRESS
    rfem_app.set_base_data(base_data=base_data)

    # Create model
    rfem_app.delete_all_objects()

    rfem_app.create_object_list(
        objs=
            define_structure()+
            define_loading()+
            define_concrete_design()
    )

    # Calculate model
    rfem_app.calculate_all(skip_warnings=False)

    # Retrieve required reinforcement by location
    required_reinf_df = rfem_app.get_result_table(
        table=rfem.results.CONCRETE_DESIGN_REQUIRED_REINFORCEMENT_AREA_ON_MEMBERS_BY_LOCATION_TABLE,
        loading=None
    ).data

    # Retrieve design check ratios for section resistance
    design_ratios_df = rfem_app.get_results(
        results_type=rfem.results.CONCRETE_DESIGN_MEMBERS_DESIGN_RATIOS,
    ).data
    design_check_type = "UL0100.00"
    design_check_ul0100 = design_ratios_df.loc[design_ratios_df['design_check_type'] == design_check_type]
    design_check_desc = design_ratios_df.loc[design_ratios_df['design_check_type'] == design_check_type, 'design_check_description'].values[0]
    print(f"\nDesign Check Ratios | {design_check_type} | {design_check_desc}:\n {design_check_ul0100}")

    # Get bottom reiforcement design check details
    bottom_reinf_location_max = get_max_req_reinf_location(required_reinf_df, ReinforcementLayer.BOTTOM)
    bottom_reinf_details_id = get_design_check_details_id_for_location(design_check_ul0100, bottom_reinf_location_max)
    bottom_reinf_details = rfem_app.get_results(
        results_type=rfem.results.CONCRETE_DESIGN_DESIGN_CHECK_DETAILS,
        filters=[
            rfem.results.ResultsFilter(
                column_id="design_check_details_id",
                filter_expression=str(bottom_reinf_details_id)
            )
        ],
    ).data

    print(f"\nBottom Reinforcement | Location = {bottom_reinf_location_max} [m]:")
    print(get_design_check_value_by_key(bottom_reinf_details, key='a_s_z_bottom'))
    print(get_design_check_value_by_key(bottom_reinf_details, key='m_y_ed'))
    print(get_design_check_value_by_key(bottom_reinf_details, key='m_y_rd'))
    print(get_design_check_value_by_key(bottom_reinf_details, key='x_rd'))
    print(get_design_check_value_by_key(bottom_reinf_details, key='eta'))


    # Get top reiforcement design check details
    top_reinf_location_max = get_max_req_reinf_location(required_reinf_df, ReinforcementLayer.TOP)
    top_reinf_details_id = get_design_check_details_id_for_location(design_check_ul0100, top_reinf_location_max)
    top_reinf_details = rfem_app.get_results(
        results_type=rfem.results.CONCRETE_DESIGN_DESIGN_CHECK_DETAILS,
        filters=[
            rfem.results.ResultsFilter(
                column_id="design_check_details_id",
                filter_expression=str(top_reinf_details_id)
            )
        ],
    ).data

    print(f"\nTop Reinforcement | Location = {top_reinf_location_max} [m]:")
    print(get_design_check_value_by_key(top_reinf_details, key='a_s_z_top'))
    print(get_design_check_value_by_key(top_reinf_details, key='m_y_ed'))
    print(get_design_check_value_by_key(top_reinf_details, key='m_y_rd'))
    print(get_design_check_value_by_key(top_reinf_details, key='x_rd'))
    print(get_design_check_value_by_key(top_reinf_details, key='eta'))