该示例显示的是梁上的水荷载的计算,水荷载随着梁的挠度而增加。 为了更加灵活,用户应该能够选择梁。 此外,作用在屋面上的附加荷载,无论水荷载如何,都适用于同一荷载工况,不应该进行修改。 已知/应用以下边界条件:
- 未变形结构体系上方的水位
- 面荷载的杆件受压区宽度
- 应用荷载的荷载工况编号
- 每米水位的水面荷载 (10000 N/m³)
- 用于识别面荷载的标识符
因此程序中定义了以下变量:
- code.sharp#
double h_water = 0.1;//未变形结构上的水高[m]
w_ref = 2;//面荷载的参考宽度 [m]
int load_case_no = 1;//应用荷载的荷载工况编号
string water_accu_comment = "积水";//标识字符串
double std_magnitude = 10000;//单位水位的面荷载[N/m^3]
- /代码#
该计划必须包括以下内容:
- 筛选出所选杆件
- 删除以前运行的水荷载
- 创建新荷载
- 开始计算
- 计算挠度
- 返回第 3 步,创建新的变形荷载
- 重复迭代,直到达到极限值
除了这些功能外,还需要与程序和模型的接口、各种 ry-catch 块以及其他标准组件,这里不再一一列举。 这些功能都包含在源代码中,源代码可以在本文下方下载。
1. 筛选出所选杆件
首先,我们使用 get_all_selected_objects 函数获取所有选定对象的信息。 接收到的数组包含 object_location 类型的元素,例如可以是类型、编号和高阶的“父”对象编号。 在下面的循环中,提取类型为 E_OBJECT_TYPE_MEMBER 的所有对象(即所有杆件编号)的编号并保存在数组 mem_noes_sel 中。
- code.csharp#
//得到选择的对象
object_location[] obj_locs = model.get_all_selected_objects();
//提取杆件
int[] mem_noes_sel = new int[0];
foreach(obj_locs中的object_location obj_loc)
{
if(obj_loc.type == object_types.E_OBJECT_TYPE_MEMBER)
{
Array.Resize(ref mem_noes_sel, mem_noes_sel.Length + 1);
mem_noes_sel[mem_noes_sel.Length-1] = obj_loc.no;
}
}
- /代码#
2.删除以前运行的水荷载
通过杆件编号,现在可以从所有杆件荷载中筛选出关联的杆件荷载。 该编号在杆件荷载编号上设置了一个循环。 在该循环中,我们将获取杆件荷载的数据,检查杆件编号是否与选择的杆件编号一致,如果匹配,则删除相应的杆件荷载:
- code.csharp#
//删除所有精确水荷载
//得到所有杆件荷载编号
int[] mem_load_noes = model.get_all_object_numbers(object_types.E_OBJECT_TYPE_MEMBER_LOAD, load_case_no);
//循环计算荷载工况的所有杆件荷载
foreach(int mem_load_no in mem_load_noes)
{
//获取杆件荷载
member_load mem_load = model.get_member_load(mem_load_no, load_case_no);
if(mem_load.comment == water_accu_comment)
{
//循环计算杆件荷载的杆件
for(int i= 0; i < mem_load.members.Length; i+ +)
{
//循环计算杆件荷载的杆件
for (int j = 0; j < mem_noes_sel.Length; j++)
{
if(mem_load.members[i] == mem_noes_sel[j])
{
//删除杆件荷载
model.delete_object(object_types.E_OBJECT_TYPE_MEMBER_LOAD, mem_load_no, load_case_no);
}
}
}
}
}
- /代码#
为了不覆盖其他杆件荷载,在下一步中将读取上次使用的杆件荷载编号:
- code.csharp#
//获取最后一个荷载编号
int no_offset = model.get_nth_object_number(object_types.E_OBJECT_TYPE_MEMBER_LOAD,0, load_case_no) + 1;
- /代码#
现在下一步是创建新的杆件荷载,这已经是 do-while 迭代循环的一部分。 该循环的原理如下:
- code.csharp#
do
{
//重置增量变形
delta_def = 0;
//施加荷载
model.begin_modification("荷载");
- //为每根杆件创建杆件荷载
...
- model.finish_modification();
- ...
//计算荷载工况
...
//得到杆件末端变形
...
//检查准则
while (delta_def > 0.0001);
- /代码#
为了停止迭代循环,选择了在结果筛选时确定的变形的变化。 如果所有变形与上一次计算的变形的偏差小于 0.0001 m(即 0.1 mm),则循环停止。
3.新建荷载
荷载类型选择为沿全局z方向作用的梯形荷载,杆件的始端和末端可以有不同的值。 请注意,对于所有要传递的参数,相关“指定”变量必须设为“真”。 这是为了不传输一个等级的所有参数,并使传输的数据量保持在较低水平。 荷载 s 的值是根据初始高度 h_water (在给定的情况下)和这个位置上的节点附加变形计算得出的。 将单位[m]的高度与单位[N/m3 ]的std_magnitude相乘,再乘以单位[m]的线荷载,得出单位[N/m]的线荷载:
- code.csharp#
//为每根杆件创建杆件荷载
for (int i = 0; i < mem_noes_sel.Length; ++i)
{
member_load mem_load = new member_load();
mem_load.no = no_offset + i;
mem_load.comment = water_accu_comment;
mem_load.members = new int[] { mem_noes_sel[i] };
mem_load.distance_a_is_defined_as_relative = true;
mem_load.distance_a_is_defined_as_relativeSpecified = true;
mem_load.distance_a_relative = 0.0;
mem_load.distance_a_relativeSpecified = true;
mem_load.distance_b_is_defined_as_relative = true;
mem_load.distance_b_is_defined_as_relativeSpecified = true;
mem_load.distance_b_relative = 1.0;
mem_load.distance_b_relativeSpecified = true;
mem_load.load_direction = member_load_load_direction.LOAD_DIRECTION_GLOBAL_Z_OR_USER_DEFINED_W_TRUE;
mem_load.load_directionSpecified = true;
mem_load.load_type = member_load_load_type.LOAD_TYPE_FORCE;
mem_load.load_typeSpecified = true;
mem_load.load_distribution = member_load_load_distribution.LOAD_DISTRIBUTION_TRAPEZOIDAL;
mem_load.load_distributionSpecified = true;
- mem_load.magnitude_1 = std_magnitude * ((h_water + mem_end_defs[i,0]) * w_ref);
mem_load.magnitude_1Specified = true;
mem_load.magnitude_2 = std_magnitude * ((h_water + mem_end_defs[i,1]) * w_ref);
mem_load.magnitude_2Specified = true;
model.set_member_load(load_case_no, mem_load);
}
- /代码#
传递荷载可使用设置杆件荷载。 为了分配荷载,字符串 water_accu_comment 用作注释。 在接下来的迭代中,荷载将不再被删除,而是重新生成一个荷载。当重新定义荷载规范时,通过指定荷载编号将其覆盖。 只有在重新启动应用程序后,才需要在筛选和删除荷载时添加该注释。 此外,为指定荷载选择了相对参照,其范围为 0-100%。
下一步是开始计算。 首先,在模型中创建一个对象,对象类型为calculate_specific_loading。 该字段包含所有要计算的荷载工况/组合。 当前工况下,只创建指定编号为load_case_no的荷载工况类型的一个单元。
- code.csharp#
//计算荷载工况
calculate_specific_loading[] csl = new calculate_specific_loading[1];
csl[0] = new calculate_specific_loading();
csl[0].no = load_case_no;
csl[0].type = case_object_types.E_OBJECT_TYPE_LOAD_CASE;
model.calculate_specific(csl, true);
- /代码#
现在计算结果已经出来了,但必须过滤掉每根杆件始端和末端的全局变形。 get_results_for_members_global_deformations函数用于获取指定荷载工况和所选杆件的所有全局杆件变形。 结果的结构与 RFEM 6 中相应的表格相同。 一种方法是读取杆件长度,然后比较结果的 x 位置。 另一种变量使用给定的描述,并且所有 x 位置之后是极值。 选择的是第二种方案,当在描述中第一次出现“极值”时,使用之前的索引来查找杆件的最后一个 x 位置。 因为杆件的第一个位置也会影响第一个输入,所以这里不需要进一步筛选:
- code.csharp#
//得到杆件末端变形
for (int i = 0; i < mem_noes_sel.Length; ++i)
{
- members_global_deformations_row[] mem_defs_glbl = model.get_results_for_members_global_deformations(case_object_types.E_OBJECT_TYPE_LOAD_CASE, load_case_no, mem_noes_sel[i]);
- //取始端点
- //计算 delta 变形
- if (Math.Abs(mem_end_defs[i, 0] - mem_defs_glbl[0].row.displacement_z) > delta_def)
- delta_def = Math.Abs(mem_end_defs[i, 0] - mem_defs_glbl[0].row.displacement_z);
- mem_end_defs[i, 0] = mem_defs_glbl[0].row.displacement_z;
- //获取终点处的变形
- for(int j = 0; j < mem_defs_glbl.Length; + + j)
- {
- if (mem_defs_glbl[j].description == "极值")
- {
- //计算 delta 变形
- if (Math.Abs(mem_end_defs[i, 1] - mem_defs_glbl[j - 1].row.displacement_z) > delta_def)
- delta_def = Math.Abs(mem_end_defs[i, 1] - mem_defs_glbl[j - 1].row.displacement_z);
- mem_end_defs[i, 1] = mem_defs_glbl[j - 1].row.displacement_z;
- 打断;
- }
- }
}
- /代码#
除了确定变形外,还会计算变量 "delta_def",用于停止准则。 首先计算上一次迭代的变形值(开始时为零)与当前值的差值。 对差值取绝对值,然后找到最大值。 在迭代循环的描述中已经显示,我们在小于 0.0001 米(即 0.1 毫米)的值处停止。
在本文附带的视频中,您可以看到一方面是荷载筛选,另一方面是直到停止的迭代步骤。 在对话框的最后会显示找到的荷载。
网络服务接口为 RFEM 6/RSTAB 9 中的单元修改和读出结果提供了不计其数的选项。 使用该软件可以实现许多不同的项目。 本文介绍的软件只是一个第一步,是可以正常工作的,并且可以正常工作:
- 获取选择的元素
- 创建荷载
- 获取和筛选结果
- 通过注释筛选元素
- 删除板件
由于结构的多样性,该软件可以作为模板用于其他项目。