该示例显示了施加在梁上的水荷载,该水荷载由于梁的挠度'而增加。 为了更加灵活,用户应该能够选择梁。 此外,与水荷载无关的作用在同一荷载工况上的附加荷载也不能修改。 已知/应用以下边界条件:
- 未变形体系以上的水位
- 面荷载的杆件进给区宽度
- 荷载工况编号
- 每米水位的面积荷载 (10000 N/m³)
- 用于识别面荷载的标识符
因此在程序中创建了以下变量:
双倍 h_water = 0.1;//未变形系统上的水高 [m]
双 w_ref = 2;//面荷载的参考宽度 [m]
int load_case_no = 1;//施加荷载的荷载工况编号
string water_accu_comment = "积水";//标识字符串
双倍 std_magnitude = 10000;//单位水高的面荷载 [N/m^3]
关于实施,该计划必须包括以下要素:
- 过滤掉所选杆件
- 删除以前运行的水荷载
- 新建荷载
- 开始计算
- 确定挠度
- 返回步骤 3,通过变形创建新的荷载
- 重复迭代,直到达到极限值
除了这些功能之外,程序还需要与程序和模型连接、try-catch 模块以及其他一些规范元素,在此不再赘述。 这些元素包含在源代码中,可以在文章下方下载。
1. 筛选出所选杆件
首先,我们使用 get_all_selected_objects 函数获取所有所选对象的信息。 得到的数组包含 object_location 类型的元素,例如对象的类型、编号和上级“父”对象编号。 在接下来的循环中,将提取类型为 E_OBJECT_TYPE_MEMBER 的所有对象的编号(即所有杆件编号),并将其保存在 mem_noes_sel 数组中。
//获取所选对象
object_location[] obj_locs = model.get_all_selected_objects();
//提取成员
int[] mem_noes_sel = new int[0];
foreach(object_location obj_loc in obj_locs)
{
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. 删除之前运行的水荷载
现在可以通过杆件编号从所有杆件荷载中过滤掉相关的杆件荷载。 使用了覆盖杆件荷载编号的环。 在这个循环中,我们获取杆件荷载数据,检查其杆件编号是否与所选杆件编号一致,如果匹配,则删除相应的杆件荷载:
//删除所有 water_accu 荷载
//获取所有的杆件荷载编号
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);
如果(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);
}
}
}
}
}
为了不覆盖其他杆件荷载,在下一步中读取最后使用的杆件荷载编号:
//获取最后的荷载编号
int no_offset = model.get_nth_object_number(object_types.E_OBJECT_TYPE_MEMBER_LOAD,0, load_case_no) + 1;
现在,下一步是创建新的杆件荷载,这已经是 do-while 迭代循环的一部分。 该循环的构建如下:
do
{
//重置增量变形
delta_def = 0;
//施加荷载
model.begin_modification("荷载");
//为每个杆件创建杆件荷载
...
model.finish_modification();
...
//计算荷载工况
...
//获取杆件末端变形
...
//检查准则
} while (delta_def > 0.0001);
为了停止迭代循环,选择了在过滤结果时确定的变形变化。 如果所有变形与上一次运行的变形偏差小于0.0001 m(即0.1 mm),则循环停止。
3. 新建荷载
荷载类型选择在全局 z 方向上作用的梯形荷载,该荷载类型在杆件始端和末端的取值可能不同。 请注意,对于所有要传送的参数,必须将相关的“Specified”变量设置为“true”。 这是必要的,因为它不会传递一个类的所有参数,并且可以保持要传递的数据量很小。 荷载's 的值由初始高度“h_water”(已指定)和该位置的附加节点变形计算得出。 高度 [m] 乘以 "std_magnitude" [N/m3 ] 和进给区宽度 [m],得出线荷载, [N/m]:
//为每个杆件创建杆件荷载
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);
}
set_member_load 函数用于传递荷载。 为了分配荷载,使用 water_accu_comment 字符串作为注释。 在接下来的迭代中不再删除荷载;而是通过指定荷载编号,在再次传输时将其覆盖。 因此只有在重新启动应用程序时过滤和删除荷载时才需要该注释。 此外,在指定荷载时选择了一个相对参考值,但其范围为 0-100%。
下一步是开始计算。 首先创建一个字段,其中包含 calculate_specific_loading 类型的对象。 该字段包含所有要计算的荷载工况/组合。 现在只创建一个荷载工况编号为 load_case_no 的单元:
//计算荷载工况
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位置。 因为杆件的第一个位置也会影响第一个条目,所以这里不需要进一步过滤:
//获取杆件末端变形
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 m(即 0.1 mm)的值处停止。
在本文随附的视频中,您可以看到一方面是荷载过滤器,另一方面是迭代步长。 最后显示找到的荷载。
网络服务接口提供了无数的选项,用于在 RFEM 6/RSTAB 9 中修改单元,以及读取结果。 许多不同的项目可以用它来实现。 本文中显示的程序仅包含许多不同元素的第一步:
- 获取所选元素
- 创建荷载
- 获取和筛选结果
- 按注释过滤元素
- 删除板件
由于这种多样性,该程序还可以作为其他项目的模板。