1599x
001773
2022-10-18

C# 中用于形成水袋的网络服务工具

RFEM 6、RSTAB 9 和 RSECTION 的 API 是基于网络服务的概念。 为了更好地介绍该主题,在下面的文章中将进一步使用C#示例进行说明。

该示例显示了施加在梁上的水荷载,该水荷载由于梁的挠度'而增加。 为了更加灵活,用户应该能够选择梁。 此外,与水荷载无关的作用在同一荷载工况上的附加荷载也不能修改。 已知/应用以下边界条件:

  • 未变形体系以上的水位
  • 面荷载的杆件进给区宽度
  • 荷载工况编号
  • 每米水位的面积荷载 (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]


关于实施,该计划必须包括以下要素:

  1. 过滤掉所选杆件
  2. 删除以前运行的水荷载
  3. 新建荷载
  4. 开始计算
  5. 确定挠度
  6. 返回步骤 3,通过变形创建新的荷载
  7. 重复迭代,直到达到极限值

除了这些功能之外,程序还需要与程序和模型连接、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 中修改单元,以及读取结果。 许多不同的项目可以用它来实现。 本文中显示的程序仅包含许多不同元素的第一步:

  1. 获取所选元素
  2. 创建荷载
  3. 获取和筛选结果
  4. 按注释过滤元素
  5. 删除板件

由于这种多样性,该程序还可以作为其他项目的模板。


作者

Günthel 先生为Dlubal 软件客户提供技术支持。

下载