Semi-Rigid Hinge#
|
Generating a semi-rigid hinge from a steel joint’s initial stiffness and comparing its effect on the beam deflection:
Keywords:
steel joint semi-rigid hinge stiffness analysis initial stiffness rotational stiffness beam deflection |
from math import inf
from dlubal.api import rfem, common
from dlubal.api.common.packing import wrap_value
# -------------------------------------------------------
# This example demonstrates how a steel joint stiffness analysis affects
# the structural response of a beam-to-column connection in RFEM.
#
# Step 1:
# Build the base model WITHOUT a steel joint (rigid connection) and
# calculate the beam deflection for the ULS design situation.
#
# Step 2 (this version):
# Add the steel joint (end plate + stiffeners) with the stiffness analysis
# extension: the Beam component gets the stiffness analysis direction My, and
# the stiffness analysis configuration is set to generate a hinge in the
# global model using the joint's initial rotational stiffness.
# The model is recalculated and the new beam deflection is compared against
# the rigid reference.
# -------------------------------------------------------
# Editable parameters (SI units)
COLUMN_CROSS_SECTION = "HEA 300"
BEAM_CROSS_SECTION = "IPE 400"
STEEL_GRADE = "S355"
PLATE_THICKNESS = "0.014"
STIFFENER_THICKNESS = "0.014"
def define_structure() -> list:
"""Define the base RFEM model (column + beam) used for the analysis."""
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, the ULS design situation and one load combination."""
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.
The Beam component (member 3) is given the stiffness analysis direction My,
so the stiffness analysis evaluates its rotational stiffness about the
major axis.
"""
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,
# Stiffness analysis direction for the Beam: My.
stiffness_analysis_directions=[
rfem.steel_joints_objects.SteelJoint.MembersRow.StiffnessAnalysisDirections.STIFFNESS_ANALYSIS_DIRECTIONS_MY,
],
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 / stiffness 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(),
),
]
# -------------------------------------------------------
# MAIN SCRIPT
# -------------------------------------------------------
with rfem.Application() as rfem_app:
# Initialize model
rfem_app.close_all_models(save_changes=False)
rfem_app.create_model(name='steel_joint_semi_rigid_hinge')
# Activate the Steel Joints add-on
base_data = rfem_app.get_base_data()
base_data.addons.steel_joints_active = True
rfem_app.set_base_data(base_data=base_data)
rfem_app.delete_all_objects()
# --- Step 1: Rigid Connection (no Steel Joint) ---
rfem_app.create_object_list(
define_structure() +
define_loading()
)
# Calculate the ULS design situation
rfem_app.calculate_all(skip_warnings=True)
# Retrieve beam deflection of the rigid connection
member_deformation_df: common.Table = rfem_app.get_results(
results_type=rfem.results.ResultsType.STATIC_ANALYSIS_MEMBERS_LOCAL_DEFORMATIONS,
filters=[
rfem.results.ResultsFilter(
column_id="loading",
filter_expression="DS1",
),
rfem.results.ResultsFilter(
column_id="member_no",
filter_expression="3",
),
],
).data
rigid_deflection = member_deformation_df["u_z"].abs().max()
print("Beam deflection - ULS design situation (DS1):")
print(f"Rigid connection (no steel joint): max |u_z| = {rigid_deflection * 1000:.3f} mm")
# --- Step 2: Steel Joint with initial stiffness ---
# Create the steel joint
rfem_app.create_object_list(
define_steel_joint()
)
# Active hinge in the global model using the joint's initial stiffness
settings_tree = rfem_app.get_object(
obj=rfem.steel_joints_design_addon_objects.JointStiffnessAnalysisConfiguration(no=1)
).settings_ec3
common.tree_table.set_values_by_key(settings_tree, "initial_stiffness", values=[True])
common.tree_table.set_values_by_key(settings_tree, "generate_hinges", values=[True])
rfem_app.update_object(
obj=rfem.steel_joints_design_addon_objects.JointStiffnessAnalysisConfiguration(
no=1,
settings_ec3=settings_tree,
)
)
# Recalculate with the joint hinge active
rfem_app.calculate_all(skip_warnings=True)
# Beam deflection with the semi-rigid joint hinge
member_deformation_df: common.Table = rfem_app.get_results(
results_type=rfem.results.ResultsType.STATIC_ANALYSIS_MEMBERS_LOCAL_DEFORMATIONS,
filters=[
rfem.results.ResultsFilter(
column_id="loading",
filter_expression="DS1",
),
rfem.results.ResultsFilter(
column_id="member_no",
filter_expression="3",
),
],
).data
joint_deflection = member_deformation_df["u_z"].abs().max()
print(f"Steel joint (initial stiffness hinge): max |u_z| = {joint_deflection * 1000:.3f} mm")
# Read the joint's rotational stiffness (S_My) from the stiffness analysis results
stiffness_df: common.Table = rfem_app.get_result_table(
table=rfem.results.ResultTable.STEEL_JOINTS_STIFFNESS_ANALYSIS_RESULTS_TABLE,
loading=rfem.ObjectId(
no=1,
object_type=rfem.OBJECT_TYPE_DESIGN_SITUATION,
),
).data
beam_row = stiffness_df.loc[stiffness_df["status"] == "beam"].iloc[0]
s_my_positive = float(beam_row["rotational_stiffness_y_positive"])
s_my_negative = float(beam_row["rotational_stiffness_y_negative"])
print("\nSteel joint stiffness analysis results (Beam):")
print(f"Rotational stiffness S_My+ = {s_my_positive / 1e6:.1f} MNm/rad")
print(f"Rotational stiffness S_My- = {s_my_negative / 1e6:.1f} MNm/rad")
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Common = Dlubal.Api.Common;
using Google.Protobuf;
using Rfem = Dlubal.Api.Rfem;
// -------------------------------------------------------
// This example demonstrates how a steel joint stiffness analysis affects
// the structural response of a beam-to-column connection in RFEM.
//
// Step 1:
// Build the base model WITHOUT a steel joint (rigid connection) and
// calculate the beam deflection for the ULS design situation.
//
// Step 2:
// Add the steel joint (end plate + stiffeners) with the stiffness analysis
// extension and set the stiffness analysis configuration to generate a hinge
// in the global model using the joint's initial rotational stiffness.
// The model is recalculated and the new beam deflection is compared against
// the rigid reference.
// -------------------------------------------------------
// Editable parameters (SI units)
const string MODEL_NAME = "steel_joint_semi_rigid_hinge";
const string COLUMN_CROSS_SECTION = "HEA 300";
const string BEAM_CROSS_SECTION = "IPE 400";
const string STEEL_GRADE = "S355";
const string PLATE_THICKNESS = "0.014";
const string STIFFENER_THICKNESS = "0.014";
static List<IMessage> DefineStructure()
{
return new List<IMessage>
{
// Materials
new Rfem.StructureCore.Material
{
No = 1,
Name = STEEL_GRADE,
},
// Cross-Sections
new Rfem.StructureCore.CrossSection
{
No = 1,
Material = 1,
Name = COLUMN_CROSS_SECTION,
},
new Rfem.StructureCore.CrossSection
{
No = 2,
Material = 1,
Name = BEAM_CROSS_SECTION,
},
// Nodes
new Rfem.StructureCore.Node
{
No = 1,
Coordinate1 = 0.0,
Coordinate2 = 0.0,
Coordinate3 = 0.0,
},
new Rfem.StructureCore.Node
{
No = 2,
Type = Rfem.StructureCore.Node.Types.Type.OnMember,
OnMemberReferenceMember = 1,
DistanceFromStartIsDefinedAsRelative = false,
DistanceFromStartAbsolute = 1.0,
},
new Rfem.StructureCore.Node
{
No = 3,
Coordinate1 = 1.0,
Coordinate2 = 0.0,
Coordinate3 = -1.0,
},
new Rfem.StructureCore.Node
{
No = 4,
Coordinate1 = 0.0,
Coordinate2 = 0.0,
Coordinate3 = -2.0,
},
// Lines
new Rfem.StructureCore.Line
{
No = 1,
DefinitionNodes = { 1, 4 },
},
new Rfem.StructureCore.Line
{
No = 3,
DefinitionNodes = { 2, 3 },
},
// Members
new Rfem.StructureCore.Member
{
No = 1,
Line = 1,
Type = Rfem.StructureCore.Member.Types.Type.Beam,
CrossSectionStart = 1,
},
new Rfem.StructureCore.Member
{
No = 3,
Line = 3,
Type = Rfem.StructureCore.Member.Types.Type.Beam,
CrossSectionStart = 2,
},
// Nodal Supports
new Rfem.TypesForNodes.NodalSupport
{
No = 1,
Nodes = { 1 },
SpringX = double.PositiveInfinity,
SpringY = double.PositiveInfinity,
SpringZ = double.PositiveInfinity,
RotationalRestraintX = double.PositiveInfinity,
RotationalRestraintY = double.PositiveInfinity,
RotationalRestraintZ = double.PositiveInfinity,
},
};
}
static List<IMessage> DefineLoading()
{
return new List<IMessage>
{
new Rfem.Loading.StaticAnalysisSettings
{
No = 1,
},
new Rfem.Loading.LoadCase
{
No = 1,
Name = "Nodal force",
StaticAnalysisSettings = 1,
SelfWeightActive = false,
},
new Rfem.Loading.DesignSituation
{
No = 1,
Name = "ULS (STR/GEO) - Permanent and transient - Eq. 6.10",
DesignSituationType = Rfem.Loading.DesignSituation.Types.DesignSituationType.StrPermanentAndTransient610,
ActiveForSteelJoints = true,
},
new Rfem.Loading.LoadCombination
{
No = 1,
DesignSituation = 1,
Name = "CO1 - 1.0 * LC1",
StaticAnalysisSettings = 1,
Items = new Rfem.Loading.LoadCombination.Types.ItemsTable
{
Rows =
{
new Rfem.Loading.LoadCombination.Types.ItemsRow
{
No = 1,
Factor = 1.0,
LoadCase = 1,
},
},
},
CombinationRuleStr = "1.0*LC1",
},
new Rfem.Loads.NodalLoad
{
No = 1,
Nodes = { 3 },
LoadCase = 1,
ForceMagnitude = 70000,
LoadDirection = Rfem.Loads.NodalLoad.Types.LoadDirection.GlobalZOrUserDefinedWTrueLength,
},
new Rfem.Loads.NodalLoad
{
No = 2,
Nodes = { 4 },
LoadCase = 1,
ComponentsForce = new Common.Vector3d { Z = 20000 },
ComponentsMoment = new Common.Vector3d { Y = 25000 },
LoadType = Rfem.Loads.NodalLoad.Types.LoadType.Components,
},
};
}
static Rfem.SteelJointsObjects.SteelJoint.Types.MembersTable DefineJointMembers()
{
// The Beam component (member 3) should use the stiffness analysis direction My.
//
// NOTE: The 'stiffness_analysis_directions' field on MembersRow is present in the
// Python API bindings but is not exposed in the C# bindings shipped in this
// repository, so it cannot be set here. The joint still evaluates the rotational
// stiffness (My) for the Beam; if/when the C# bindings are regenerated, add:
// StiffnessAnalysisDirections = { ...MembersRow.Types.StiffnessAnalysisDirections.My }
return new Rfem.SteelJointsObjects.SteelJoint.Types.MembersTable
{
Rows =
{
new Rfem.SteelJointsObjects.SteelJoint.Types.MembersRow
{
No = 1,
IsActive = true,
MembersNo = { 1 },
Status = "Column",
EndType = Rfem.SteelJointsObjects.SteelJoint.Types.MembersRow.Types.EndType.MemberContinuous,
Supported = true,
},
new Rfem.SteelJointsObjects.SteelJoint.Types.MembersRow
{
No = 2,
IsActive = true,
MembersNo = { 3 },
Status = "Beam",
EndType = Rfem.SteelJointsObjects.SteelJoint.Types.MembersRow.Types.EndType.MemberEnded,
StiffnessAnalysisDirections =
{
Rfem.SteelJointsObjects.SteelJoint.Types.MembersRow.Types.StiffnessAnalysisDirections.My
},
Supported = false,
},
},
};
}
static Common.Value WrapValue(object value)
{
// Create a generic Common.Value from a plain value, mirroring the Python
// wrap_value() helper (bool / int / double / string oneof).
return value switch
{
bool b => new Common.Value { BoolValue = b },
int i => new Common.Value { IntValue = i },
double d => new Common.Value { DoubleValue = d },
string s => new Common.Value { StringValue = s },
_ => new Common.Value { StringValue = value?.ToString() ?? string.Empty },
};
}
static Rfem.SteelJointsObjects.SteelJoint.Types.ComponentsTable DefineJointComponents()
{
var jointComponents = new List<(
Rfem.SteelJointsObjects.SteelJoint.Types.ComponentsRow.Types.Type Type,
string Name,
List<(string Key, object Value)> Settings)>
{
(
Rfem.SteelJointsObjects.SteelJoint.Types.ComponentsRow.Types.Type.EndPlate,
"End Plate 1",
new List<(string, object)>
{
("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.SteelJointsObjects.SteelJoint.Types.ComponentsRow.Types.Type.Stiffener,
"Stiffener 1",
new List<(string, object)>
{
("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.SteelJointsObjects.SteelJoint.Types.ComponentsRow.Types.Type.Stiffener,
"Stiffener 2",
new List<(string, object)>
{
("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),
}
),
};
var componentsTable = new Rfem.SteelJointsObjects.SteelJoint.Types.ComponentsTable();
int componentNo = 1;
foreach (var (type, name, settings) in jointComponents)
{
var settingsTable = new Rfem.SteelJointsObjects.SteelJoint.Types.ComponentsRow.Types.SettingsTable();
int settingNo = 1;
foreach (var (key, value) in settings)
{
settingsTable.Rows.Add(new Rfem.SteelJointsObjects.SteelJoint.Types.ComponentsRow.Types.SettingsTableRow
{
No = settingNo,
Key = key,
Value = WrapValue(value),
});
settingNo++;
}
componentsTable.Rows.Add(new Rfem.SteelJointsObjects.SteelJoint.Types.ComponentsRow
{
No = componentNo,
IsActive = true,
Type = type,
Name = name,
Settings = settingsTable,
});
componentNo++;
}
return componentsTable;
}
static List<IMessage> DefineSteelJoint()
{
return new List<IMessage>
{
new Rfem.SteelJointsDesignAddonObjects.JointUlsConfiguration
{
No = 1,
Name = "ULS Configuration",
},
new Rfem.SteelJointsDesignAddonObjects.JointStiffnessAnalysisConfiguration
{
No = 1,
Name = "Stiffness Analysis Configuration",
},
new Rfem.SteelJointsObjects.SteelJoint
{
No = 1,
Nodes = { 2 },
UserDefinedNameEnabled = true,
Name = "Nodes : 2 | Created via API",
Comment = "Created via API",
UltimateConfiguration = 1,
StiffnessAnalysisConfiguration = 1,
Members = DefineJointMembers(),
Components = DefineJointComponents(),
},
};
}
// -------------------------------------------------------
// MAIN SCRIPT
// -------------------------------------------------------
ApplicationRfem? rfemApp = null;
try
{
rfemApp = new ApplicationRfem();
// Initialize model
rfemApp.close_all_models(saveChanges: false);
rfemApp.create_model(name: MODEL_NAME);
// Activate the Steel Joints add-on
var baseData = rfemApp.get_base_data();
baseData.Addons.SteelJointsActive = true;
rfemApp.set_base_data(baseData: baseData);
rfemApp.delete_all_objects();
// --- Step 1: Rigid Connection (no Steel Joint) ---
rfemApp.create_object_list(
DefineStructure()
.Concat(DefineLoading())
.ToList()
);
// Calculate the ULS design situation
rfemApp.calculate_all(skipWarnings: true);
// Retrieve beam deflection of the rigid connection
var memberDeformation = rfemApp.get_results(
resultsType: Rfem.Results.ResultsType.StaticAnalysisMembersLocalDeformations,
filters: new List<Rfem.Results.ResultsFilter>
{
new Rfem.Results.ResultsFilter { ColumnId = "loading", FilterExpression = "DS1" },
new Rfem.Results.ResultsFilter { ColumnId = "member_no", FilterExpression = "3" },
}
);
var rigidDeflection = memberDeformation.Data.Rows
.Select(row => Math.Abs(Convert.ToDouble(row["u_z"], CultureInfo.InvariantCulture)))
.Max();
Console.WriteLine("Beam deflection - ULS design situation (DS1):");
Console.WriteLine($"Rigid connection (no steel joint): max |u_z| = {rigidDeflection * 1000:F3} mm");
// --- Step 2: Steel Joint with initial stiffness ---
// Create the steel joint
rfemApp.create_object_list(DefineSteelJoint());
// Activate hinge in the global model using the joint's initial stiffness
var settingsTree = rfemApp.get_object<Rfem.SteelJointsDesignAddonObjects.JointStiffnessAnalysisConfiguration>(
new Rfem.SteelJointsDesignAddonObjects.JointStiffnessAnalysisConfiguration { No = 1 }
).SettingsEc3;
Common.TreeTable.SetValuesByKey(settingsTree, "initial_stiffness", new List<object> { true });
Common.TreeTable.SetValuesByKey(settingsTree, "generate_hinges", new List<object> { true });
rfemApp.update_object(
obj: new Rfem.SteelJointsDesignAddonObjects.JointStiffnessAnalysisConfiguration
{
No = 1,
SettingsEc3 = settingsTree,
}
);
// Recalculate with the joint hinge active
rfemApp.calculate_all(skipWarnings: true);
// Beam deflection with the semi-rigid joint hinge
memberDeformation = rfemApp.get_results(
resultsType: Rfem.Results.ResultsType.StaticAnalysisMembersLocalDeformations,
filters: new List<Rfem.Results.ResultsFilter>
{
new Rfem.Results.ResultsFilter { ColumnId = "loading", FilterExpression = "DS1" },
new Rfem.Results.ResultsFilter { ColumnId = "member_no", FilterExpression = "3" },
}
);
var jointDeflection = memberDeformation.Data.Rows
.Select(row => Math.Abs(Convert.ToDouble(row["u_z"], CultureInfo.InvariantCulture)))
.Max();
Console.WriteLine($"Steel joint (initial stiffness hinge): max |u_z| = {jointDeflection * 1000:F3} mm");
// Read the joint's rotational stiffness (S_My) from the stiffness analysis results.
// The stiffness analysis results are exposed as a pre-processed result table via
// get_result_table - there is no matching ResultsType for get_results. The table
// is tree-shaped: a header row per joint, followed by one row per joint component
// (status 'column' / 'beam'). This model has a single joint, so the Beam row is
// selected directly by its status.
var stiffness = rfemApp.get_result_table(
table: Rfem.Results.ResultTable.SteelJointsStiffnessAnalysisResultsTable,
loading: new Rfem.ObjectId
{
No = 1,
ObjectType = Rfem.ObjectType.DesignSituation,
}
);
var beamRow = stiffness.Data.Rows
.First(row => Convert.ToString(row["status"], CultureInfo.InvariantCulture) == "beam");
var sMyPositive = Convert.ToDouble(beamRow["rotational_stiffness_y_positive"], CultureInfo.InvariantCulture);
var sMyNegative = Convert.ToDouble(beamRow["rotational_stiffness_y_negative"], CultureInfo.InvariantCulture);
Console.WriteLine("\nSteel joint stiffness analysis results (Beam):");
Console.WriteLine($"Rotational stiffness S_My+ = {sMyPositive / 1e6:F1} MNm/rad");
Console.WriteLine($"Rotational stiffness S_My- = {sMyNegative / 1e6:F1} MNm/rad");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
finally
{
if (rfemApp != null) rfemApp.close_connection();
}