Beam to Column Flange#
|
Creating a beam-to-column end-plate steel joint and reading its governing design checks:
Keywords:
steel joint beam to column end plate bolts stiffeners design ratios |
from math import inf
from dlubal.api import rfem, common
from dlubal.api.common.packing import wrap_value
import re
# -------------------------------------------------------
# This example demonstrates how to create a simple steel joint in RFEM.
# It defines a column and beam connection, activates the Steel Joints add-on,
# and creates joint components for an end plate and stiffeners.
# -------------------------------------------------------
# Editable parameters (SI units)
COLUMN_CROSS_SECTION = "HEA 300"
BEAM_CROSS_SECTION = "IPE 400"
STEEL_GRADE = "S355"
BOLT_SIZE = "M16"
BOLT_GRADE = "8.8"
PLATE_THICKNESS = "0.014"
STIFFENER_THICKNESS = "0.014"
def define_structure() -> list:
"""Define the base RFEM model required by the steel joint."""
return [
# Materials
rfem.structure_core.Material(
no=1,
name=STEEL_GRADE,
),
# Cross-Sections
rfem.structure_core.CrossSection(
no=1,
material=1,
name=COLUMN_CROSS_SECTION,
),
rfem.structure_core.CrossSection(
no=2,
material=1,
name=BEAM_CROSS_SECTION,
),
# Nodes
rfem.structure_core.Node(
no=1,
coordinate_1=0.0,
coordinate_2=0.0,
coordinate_3=0.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=1.0,
),
rfem.structure_core.Node(
no=3,
coordinate_1=1.0,
coordinate_2=0.0,
coordinate_3=-1.0,
),
rfem.structure_core.Node(
no=4,
coordinate_1=0.0,
coordinate_2=0.0,
coordinate_3=-2.0,
),
# Lines
rfem.structure_core.Line(
no=1,
definition_nodes=[1, 4],
),
rfem.structure_core.Line(
no=3,
definition_nodes=[2, 3],
),
# Members
rfem.structure_core.Member(
no=1,
line=1,
type=rfem.structure_core.Member.TYPE_BEAM,
cross_section_start=1,
),
rfem.structure_core.Member(
no=3,
line=3,
type=rfem.structure_core.Member.TYPE_BEAM,
cross_section_start=2,
),
# Nodal Supports
rfem.types_for_nodes.NodalSupport(
no=1,
nodes=[1],
spring_x=inf,
spring_y=inf,
spring_z=inf,
rotational_restraint_x=inf,
rotational_restraint_y=inf,
rotational_restraint_z=inf,
),
]
def define_loading() -> list:
"""Define a load case and one nodal force at the free beam end."""
return [
rfem.loading.StaticAnalysisSettings(
no=1,
),
rfem.loading.LoadCase(
no=1,
name="Nodal force",
static_analysis_settings=1,
self_weight_active=False,
),
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,
active_for_steel_joints=True,
),
rfem.loading.LoadCombination(
no=1,
design_situation=1,
name="CO1 - 1.0 * LC1",
static_analysis_settings=1,
items=rfem.loading.LoadCombination.ItemsTable(
rows=[
rfem.loading.LoadCombination.ItemsRow(
no=1,
factor=1.0,
load_case=1,
),
]
),
combination_rule_str="1.0*LC1",
),
rfem.loads.NodalLoad(
no=1,
nodes=[3],
load_case=1,
force_magnitude=70000,
load_direction=rfem.loads.NodalLoad.LOAD_DIRECTION_GLOBAL_Z_OR_USER_DEFINED_W_TRUE_LENGTH,
),
rfem.loads.NodalLoad(
no=2,
nodes=[4],
load_case=1,
components_force=common.Vector3d(z=20000),
components_moment=common.Vector3d(y=25000),
load_type=rfem.loads.NodalLoad.LOAD_TYPE_COMPONENTS
),
]
def define_joint_members():
"""Define members assigned inside the Steel Joint add-on table."""
return rfem.steel_joints_objects.SteelJoint.MembersTable(
rows=[
rfem.steel_joints_objects.SteelJoint.MembersRow(
no=1,
is_active=True,
members_no=[1],
status="Column",
end_type=rfem.steel_joints_objects.SteelJoint.MembersRow.EndType.END_TYPE_MEMBER_CONTINUOUS,
supported=True,
),
rfem.steel_joints_objects.SteelJoint.MembersRow(
no=2,
is_active=True,
members_no=[3],
status="Beam",
end_type=rfem.steel_joints_objects.SteelJoint.MembersRow.EndType.END_TYPE_MEMBER_ENDED,
supported=False,
),
]
)
def define_joint_components():
"""Define top-level Steel Joint components and their RFEM setting keys."""
joint_components = [
(
rfem.steel_joints_objects.SteelJoint.ComponentsRow.Type.TYPE_END_PLATE,
"End Plate 1",
[
("connected_member_1", "Beam"),
("reference_member", "Column"),
("plate_material_1", 1),
("plate_shape_1", 0),
("plate_thickness_1", PLATE_THICKNESS),
("plate_definition_type_1", 0),
("plate_top_offset_1", 0.01),
("plate_bottom_offset_1", 0.01),
("plate_left_offset_1", 0.005),
("plate_right_offset_1", 0.005),
("bolt_size", "M16"),
("bolt_strength_grade", "8.8"),
("bolt_horizontal_count", 2),
("bolt_horizontal_spacing", "0.0450 0.0900 0.0450"),
("bolt_vertical_count", 3),
("bolt_vertical_spacing", "0.0600 0.0500 0.1500 0.0600"),
("bolt_prestressed_bolts", False),
("bolt_shear_plane_in_thread", True),
("plate_1_bolt_is_active_1", True),
("plate_1_bolt_is_active_2", True),
("plate_1_bolt_is_active_3", True),
("plate_1_bolt_is_active_4", True),
("plate_1_bolt_is_active_5", True),
("plate_1_bolt_is_active_6", True),
("weld_is_active_1", True),
("weld_is_active_2", True),
("weld_is_active_3", True),
("weld_type_1", 2),
("weld_type_2", 2),
("weld_type_3", 2),
("weld_material_1", "Double fillet weld"),
("weld_material_2", "Double fillet weld"),
("weld_material_3", "Double fillet weld"),
("weld_size_1", 0.003),
("weld_size_2", 0.003),
("weld_size_3", 0.003),
],
),
(
rfem.steel_joints_objects.SteelJoint.ComponentsRow.Type.TYPE_STIFFENER,
"Stiffener 1",
[
("stiffened_member", "Column"),
("reference_member", "Beam"),
("plate_material", 1),
("plate_thickness", STIFFENER_THICKNESS),
("plate_count", 1),
("position", 4),
("reference_member_plate", "Flange 1"),
("direction", 0),
("location_offset", "0.0000"),
("side", 2),
("inclination", 0.0),
("width_offset", 0.0),
("height_offset", 0.0),
("chamfer", 0.025),
("weld_is_active_1", True),
("weld_is_active_2", True),
("weld_is_active_3", True),
("weld_type_1", 2),
("weld_type_2", 2),
("weld_type_3", 2),
("weld_material_1", 1),
("weld_material_2", 1),
("weld_material_3", 1),
("weld_size_1", 0.003),
("weld_size_2", 0.003),
("weld_size_3", 0.003),
],
),
(
rfem.steel_joints_objects.SteelJoint.ComponentsRow.Type.TYPE_STIFFENER,
"Stiffener 2",
[
("stiffened_member", "Column"),
("reference_member", "Beam"),
("plate_material", 1),
("plate_thickness", STIFFENER_THICKNESS),
("plate_count", 1),
("position", 4),
("reference_member_plate", "Flange 2"),
("direction", 1),
("location_offset", "0.0000"),
("side", 2),
("inclination", 0.0),
("width_offset", 0.0),
("height_offset", 0.0),
("chamfer", 0.0),
("weld_is_active_1", True),
("weld_is_active_2", True),
("weld_is_active_3", True),
("weld_type_1", 2),
("weld_type_2", 2),
("weld_type_3", 2),
("weld_material_1", 1),
("weld_material_2", 1),
("weld_material_3", 1),
("weld_size_1", 0.003),
("weld_size_2", 0.003),
("weld_size_3", 0.003),
],
),
]
joint_component_rows = []
for component_no, joint_component in enumerate(joint_components, start=1):
component_type, component_name, component_settings = joint_component
setting_rows = []
for setting_no, setting in enumerate(component_settings, start=1):
setting_key, setting_value = setting
setting_rows.append(
rfem.steel_joints_objects.SteelJoint.ComponentsRow.SettingsTableRow(
no=setting_no,
key=setting_key,
value=wrap_value(setting_value),
)
)
joint_component_rows.append(
rfem.steel_joints_objects.SteelJoint.ComponentsRow(
no=component_no,
is_active=True,
type=component_type,
name=component_name,
settings=rfem.steel_joints_objects.SteelJoint.ComponentsRow.SettingsTable(
rows=setting_rows,
),
)
)
return rfem.steel_joints_objects.SteelJoint.ComponentsTable(
rows=joint_component_rows,
)
def define_steel_joint() -> list:
"""Define the steel joint and its design configurations"""
return [
rfem.steel_joints_design_addon_objects.JointUlsConfiguration(
no=1,
name="ULS Configuration",
),
rfem.steel_joints_design_addon_objects.JointStiffnessAnalysisConfiguration(
no=1,
name="Stiffness Analysis Configuration",
),
rfem.steel_joints_objects.SteelJoint(
no=1,
nodes=[2],
user_defined_name_enabled=True,
name="Nodes : 2 | Created via API",
comment="Created via API",
ultimate_configuration=1,
stiffness_analysis_configuration=1,
members=define_joint_members(),
components=define_joint_components(),
),
]
def get_max_design_check_row(design_ratios_df, design_check_type: str):
"""Return the design result row with the maximum design ratio for a check type."""
design_checks = design_ratios_df.loc[
design_ratios_df["design_check_type"] == design_check_type
]
if design_checks.empty:
raise ValueError(f"No design check results found for {design_check_type}.")
return design_checks.loc[design_checks["design_ratio"].idxmax()]
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'. The unit string is cleaned to remove any HTML tags.
"""
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]
# 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='end_plate_moment_connection')
# Edit base data
base_data = rfem_app.get_base_data()
base_data.addons.steel_joints_active = True
rfem_app.set_base_data(base_data=base_data)
# Create model
rfem_app.delete_all_objects()
rfem_app.create_object_list(
define_structure() +
define_loading() +
define_steel_joint()
)
# Calculate design
rfem_app.calculate_all(skip_warnings=True)
# Retrieve maximum design check ratio summary
design_ratios_df: common.Table = rfem_app.get_results(
results_type=rfem.results.ResultsType.STEEL_JOINTS_DESIGN_RATIOS,
).data
max_plate_check = get_max_design_check_row(design_ratios_df, "UL1000.00") # Plates
max_bolt_check = get_max_design_check_row(design_ratios_df, "UL1100.00") # Bolts
max_weld_check = get_max_design_check_row(design_ratios_df, "UL1200.00") # Welds
print("Design check summary:")
print(f"Plates: {max_plate_check['design_ratio']}")
print(f"Bolts: {max_bolt_check['design_ratio']}")
print(f"Welds: {max_weld_check['design_ratio']}")
# Retrieve details for bolt check of maximum tension resistance
bolt_check_details_id = int(max_bolt_check["design_check_details_id"])
bolt_check_details_df = rfem_app.get_results(
results_type=rfem.results.ResultsType.STEEL_JOINTS_DESIGN_CHECK_DETAILS,
filters=[
rfem.results.ResultsFilter(
column_id="design_check_details_id",
filter_expression=str(bolt_check_details_id),
)
],
).data
print(f"\nBolt | Tension resistance:")
print(get_design_check_value_by_key(bolt_check_details_df, key='f_t_ed'))
print(get_design_check_value_by_key(bolt_check_details_df, key='f_ub'))
print(get_design_check_value_by_key(bolt_check_details_df, key='k_2'))
print(get_design_check_value_by_key(bolt_check_details_df, key='f_t_rd'))
print(get_design_check_value_by_key(bolt_check_details_df, key='eta_ft'))