Distributed Load on Beam#
|
Modelling L-frame beam under distributed load with evaluation of the stresses:
Keywords:
L-frame rectangular cross-section distributed load material properties basic stresses |
from math import inf, pi
from dlubal.api import rfem, common
# -------------------------------------------------------
# This example demonstrates how to model two perpendicular
# beams with a rectangular cross-section. The top
# (horizontal) beam is loaded by a distributed load.
# While neglecting self-weight, the maximum normal stress
# on the horizontal beam is evaluated from member forces.
# -------------------------------------------------------
# Editable parameters (SI units)
MATERIAL = "S235"
CROSS_SECTION_WIDTH = 0.025
CROSS_SECTION_HEIGHT = 0.05
VERTICAL_BEAM_LENGTH = 1.0
HORIZONTAL_BEAM_LENGTH = 1.0
DISTRIBUTED_LOAD = 10000.0
def define_structure() -> list:
"""Define and return a list of structural objects."""
return [
rfem.structure_core.Material(
no=1,
name=MATERIAL,
),
rfem.structure_core.CrossSection(
no=1,
type=rfem.structure_core.CrossSection.TYPE_PARAMETRIC_MASSIVE_I,
material=1,
b=CROSS_SECTION_WIDTH,
h=CROSS_SECTION_HEIGHT,
shear_stiffness_deactivated=True,
),
rfem.structure_core.Node(no=1, coordinate_1=0.0, coordinate_2=0.0, coordinate_3=0.0),
rfem.structure_core.Node(no=2, coordinate_1=0.0, coordinate_2=0.0, coordinate_3=-VERTICAL_BEAM_LENGTH),
rfem.structure_core.Node(no=3, coordinate_1=HORIZONTAL_BEAM_LENGTH, coordinate_2=0.0, coordinate_3=-VERTICAL_BEAM_LENGTH),
rfem.structure_core.Line(no=1, definition_nodes=[1, 2]),
rfem.structure_core.Line(no=2, definition_nodes=[2, 3]),
rfem.structure_core.Member(
no=1,
line=1,
cross_section_start=1,
#rotation_angle=pi / 2,
),
rfem.structure_core.Member(
no=2,
line=2,
cross_section_start=1,
#rotation_angle=pi / 2,
),
rfem.types_for_nodes.NodalSupport(
no=1,
nodes=[1, 3],
spring=common.Vector3d(x=inf, y=inf, z=inf),
rotational_restraint=common.Vector3d(x=inf, y=0, z=inf),
)
]
def define_loading() -> list:
"""Define and return a list of loading objects."""
return [
rfem.loading.StaticAnalysisSettings(no=1),
rfem.loading.LoadCase(
no=1,
static_analysis_settings=1,
self_weight_active=False,
),
rfem.loads.MemberLoad(
no=1,
members=[2],
load_case=1,
load_type=rfem.loads.MemberLoad.LOAD_TYPE_FORCE,
load_distribution=rfem.loads.MemberLoad.LOAD_DISTRIBUTION_UNIFORM,
magnitude=DISTRIBUTED_LOAD,
),
]
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='distributed_load_on_beam')
base_data = rfem_app.get_base_data()
base_data.addons.multilayer_surfaces_active = True
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_strains_df = rfem_app.get_results(
results_type=rfem.results.STATIC_ANALYSIS_MEMBERS_STRAINS,
filters=[
rfem.results.ResultsFilter(column_id="member_no", filter_expression="2"),
rfem.results.ResultsFilter(column_id="loading", filter_expression="LC1"),
],
).data
# Material Properties
material = rfem_app.get_object(
rfem.structure_core.Material(no=1)
)
material_values_tree = material.material_values.rows[0].material_values_tree
young_modulus = common.tree_table.get_values_by_key(
tree=material_values_tree,
key='e', # young_modulus
occurrence=1
)
print(f"young_modulus: {young_modulus}")
# Stress evaluation (horizontal beam):
# use axial strain epsilon_x and bending curvature kappa_y only
# at top and bottom fibers (z = +/- h/2).
required_columns = ["epsilon_x", "kappa_z"]
half_height = CROSS_SECTION_HEIGHT / 2
sigma_top = young_modulus * (member_strains_df["epsilon_x"] - member_strains_df["kappa_y"] * half_height)
sigma_bottom = young_modulus * (member_strains_df["epsilon_x"] + member_strains_df["kappa_y"] * half_height)
sigma_max = max(sigma_top.abs().max(), sigma_bottom.abs().max())
print(f"sigma_max: {sigma_max}")
using Google.Protobuf;
using System.Globalization;
using System.Linq;
using Common = Dlubal.Api.Common;
using Rfem = Dlubal.Api.Rfem;
// -------------------------------------------------------
// This example demonstrates how to model two perpendicular
// beams with a rectangular cross-section. The top
// (horizontal) beam is loaded by a distributed load.
// While neglecting self-weight, the maximum normal stress
// on the horizontal beam is evaluated from strains.
// -------------------------------------------------------
// Editable parameters (SI units)
const string MODEL_NAME = "distributed_load_on_beam";
const string MATERIAL = "S235";
const double CROSS_SECTION_WIDTH = 0.025;
const double CROSS_SECTION_HEIGHT = 0.05;
const double VERTICAL_BEAM_LENGTH = 1.0;
const double HORIZONTAL_BEAM_LENGTH = 1.0;
const double DISTRIBUTED_LOAD = 10000.0;
static double ParseDoubleInvariant(object? value)
{
if (value is null) return double.NaN;
if (value is double d) return d;
return double.TryParse(
Convert.ToString(value, CultureInfo.InvariantCulture),
NumberStyles.Any,
CultureInfo.InvariantCulture,
out var parsed
)
? parsed
: double.NaN;
}
static List<IMessage> DefineStructure()
{
return new List<IMessage>
{
new Rfem.StructureCore.Material
{
No = 1,
Name = MATERIAL,
},
new Rfem.StructureCore.CrossSection
{
No = 1,
Type = Rfem.StructureCore.CrossSection.Types.Type.ParametricMassiveI,
Material = 1,
B = CROSS_SECTION_WIDTH,
H = CROSS_SECTION_HEIGHT,
ShearStiffnessDeactivated = true,
},
new Rfem.StructureCore.Node
{
No = 1,
Coordinate1 = 0.0,
Coordinate2 = 0.0,
Coordinate3 = 0.0,
},
new Rfem.StructureCore.Node
{
No = 2,
Coordinate1 = 0.0,
Coordinate2 = 0.0,
Coordinate3 = -VERTICAL_BEAM_LENGTH,
},
new Rfem.StructureCore.Node
{
No = 3,
Coordinate1 = HORIZONTAL_BEAM_LENGTH,
Coordinate2 = 0.0,
Coordinate3 = -VERTICAL_BEAM_LENGTH,
},
new Rfem.StructureCore.Line
{
No = 1,
DefinitionNodes = { 1, 2 },
},
new Rfem.StructureCore.Line
{
No = 2,
DefinitionNodes = { 2, 3 },
},
new Rfem.StructureCore.Member
{
No = 1,
Line = 1,
CrossSectionStart = 1,
},
new Rfem.StructureCore.Member
{
No = 2,
Line = 2,
CrossSectionStart = 1,
},
new Rfem.TypesForNodes.NodalSupport
{
No = 1,
Nodes = { 1, 3 },
Spring = new Common.Vector3d
{
X = double.PositiveInfinity,
Y = double.PositiveInfinity,
Z = double.PositiveInfinity,
},
RotationalRestraint = new Common.Vector3d
{
X = double.PositiveInfinity,
Y = 0.0,
Z = double.PositiveInfinity,
},
},
};
}
static List<IMessage> DefineLoading()
{
return new List<IMessage>
{
new Rfem.Loading.StaticAnalysisSettings
{
No = 1,
},
new Rfem.Loading.LoadCase
{
No = 1,
StaticAnalysisSettings = 1,
SelfWeightActive = false,
},
new Rfem.Loads.MemberLoad
{
No = 1,
Members = { 2 },
LoadCase = 1,
LoadType = Rfem.Loads.MemberLoad.Types.LoadType.Force,
LoadDistribution = Rfem.Loads.MemberLoad.Types.LoadDistribution.Uniform,
Magnitude = DISTRIBUTED_LOAD,
},
};
}
ApplicationRfem? rfemApp = null;
try
{
rfemApp = new ApplicationRfem();
var appInfo = rfemApp.get_application_info();
Console.WriteLine($"\nApplication Info:\n{appInfo}");
rfemApp.create_model(name: MODEL_NAME);
var baseData = rfemApp.get_base_data();
baseData.Addons.MultilayerSurfacesActive = true;
rfemApp.set_base_data(baseData: baseData);
rfemApp.delete_all_objects();
rfemApp.create_object_list(DefineStructure());
rfemApp.create_object_list(DefineLoading());
var calculationInfo = rfemApp.calculate_all(skipWarnings: true);
Console.WriteLine($"\nCalculation Info:\n{calculationInfo}");
var memberStrains = rfemApp.get_results(
resultsType: Rfem.Results.ResultsType.StaticAnalysisMembersStrains,
filters: new List<Rfem.Results.ResultsFilter>
{
new Rfem.Results.ResultsFilter { ColumnId = "member_no", FilterExpression = "2" },
new Rfem.Results.ResultsFilter { ColumnId = "loading", FilterExpression = "LC1" },
}
);
bool hasEpsilonX = memberStrains.Data.Columns.Any(c => c.Name == "epsilon_x");
bool hasKappaY = memberStrains.Data.Columns.Any(c => c.Name == "kappa_y");
if (!hasEpsilonX || !hasKappaY)
{
var available = string.Join(", ", memberStrains.Data.Columns.Select(c => c.Name));
throw new InvalidOperationException(
$"Expected columns 'epsilon_x' and 'kappa_y' not found. Available columns: {available}"
);
}
var material = rfemApp.get_object<Rfem.StructureCore.Material>(
new Rfem.StructureCore.Material { No = 1 }
);
var materialValuesTree = material.MaterialValues.Rows[0].MaterialValuesTree;
var eValues = Common.TreeTable.GetValuesByKey(tree: materialValuesTree, key: "e", occurrence: 1);
var youngModulus = ParseDoubleInvariant(eValues.FirstOrDefault());
if (double.IsNaN(youngModulus))
{
throw new InvalidOperationException("Young's modulus could not be resolved from material values.");
}
Console.WriteLine($"young_modulus: {youngModulus}");
var epsilonXCol = memberStrains.Data.Columns["epsilon_x"];
var kappaYCol = memberStrains.Data.Columns["kappa_y"];
double halfHeight = CROSS_SECTION_HEIGHT / 2.0;
double sigmaMax = double.NaN;
for (long i = 0; i < epsilonXCol.Length; i++)
{
double epsilonX = ParseDoubleInvariant(epsilonXCol[i]);
double kappaY = ParseDoubleInvariant(kappaYCol[i]);
if (double.IsNaN(epsilonX) || double.IsNaN(kappaY))
continue;
double sigmaTop = youngModulus * (epsilonX - kappaY * halfHeight);
double sigmaBottom = youngModulus * (epsilonX + kappaY * halfHeight);
double rowMax = Math.Max(Math.Abs(sigmaTop), Math.Abs(sigmaBottom));
sigmaMax = double.IsNaN(sigmaMax) ? rowMax : Math.Max(sigmaMax, rowMax);
}
Console.WriteLine($"sigma_max: {sigmaMax}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
finally
{
if (rfemApp != null) rfemApp.close_connection();
}