第三方时历载荷数据文件转换为SACS格式
几周之前,一个同事问我能不能帮她编写一个程序,来解决项目中的一个实际问题。通过编写程序来解决实际的工程问题,哪怕细小琐碎,都是一件很有成就感的事情,因此,对于这样的请求,我一向是乐于提供帮助的,更何况对方一位曾经有过愉快合作经历、工程经验丰富、令人敬佩的女士呢?
这位同事正在使用SACS进行海上风电基础设计分析的工作,需要将厂商提供的风机时历载荷数据转换成SACS的格式。让我们先来看一下厂商提供的载荷文件的内容。
12_aa-01
H_2.38#N_5#Mbr 4 End 2
Time(s) Mx(kNm) My(kNm) Mz(kNm) Fx(kN) Fy(kN) Fz(kN)
0.000000E+00 -1.804820E+00 2.944040E+01 -7.076857E+00 -3.464086E+03 -8.995766E-01 -9.728964E+00
5.000000E-02 7.849053E-02 3.437607E+01 -1.885374E+01 -3.477202E+03 9.556743E-02 -9.438611E+00
1.000000E-01 9.640223E-01 3.683009E+01 -2.443988E+01 -3.483740E+03 6.861453E-01 -9.230765E+00
1.500000E-01 8.431264E-01 3.676036E+01 -2.453593E+01 -3.483276E+03 9.542585E-01 -8.921505E+00
2.000000E-01 -2.224573E-01 3.612463E+01 -2.079676E+01 -3.482429E+03 7.689297E-01 -8.916281E+00
...
文件的数据格式十分明了,时历载荷数据从文件的第4行开始,直到最后一行,每一行数值段的数目是相同的,各数值段对应的物理量如下表:
数值段 | 物理量 | 单位 |
---|---|---|
1 | Time | s |
2 | Mx | kNm |
3 | My | kNm |
4 | Mz | kNm |
5 | Fx | kN |
6 | Fy | kN |
7 | Fz | kN |
再来看一下SACS时历载荷文件的内容。
THLOAD MN 1.0000 1.0000
TIME 0.0000E+00
JLODJ001 -3.4641E+03 -8.9958E-01 -9.7290E+00 -1.8048E+00 2.9440E+01 -7.0769E+00
TIME 5.0000E-02
JLODJ001 -3.4772E+03 9.5567E-02 -9.4386E+00 7.8491E-02 3.4376E+01 -1.8854E+01
TIME 1.0000E-01
JLODJ001 -3.4837E+03 6.8615E-01 -9.2308E+00 9.6402E-01 3.6830E+01 -2.4440E+01
TIME 1.5000E-01
JLODJ001 -3.4833E+03 9.5426E-01 -8.9215E+00 8.4313E-01 3.6760E+01 -2.4536E+01
...
...
...
END
程序必须严格按照SACS要求的格式来准备时历载荷文件,否则就不能被SACS正确读入,甚至会导致SACS的崩溃。因此,我们需要仔细的阅读SACS的用户文档。容易看出,SACS时历载荷文件主要由以下几个输入数据行(Input line)组成:
- THLOAD
- TIME
- JLOD
- END
我们在SACS的用户文档中逐个查索相应的格式。
THLOAD
THLOAD 表示分析将包括时历载荷数据,其格式下表所示。
数据列 | 参数 | 单位 |
---|---|---|
1-6 | 行标志位 | - |
12-13 | 单位制 (MN代表公制,力的单位为kN) | - |
14-20 | 力分量的系数 | - |
21-27 | 力矩分量的系数 | - |
在本项目中,单位系统采用公制MN,力和力矩的系数都取1.0。
TIME
TIME 表示时历载荷的时间,同时也表示下一行将为JLOD数据行。
数据列 | 参数 | 单位 |
---|---|---|
1-4 | 行标志位 | - |
6-17 | 时间 | s |
JLOD
JLOD 应是Joint load的简写,其格式为
数据列 | 参数 | 单位 |
---|---|---|
1-4 | 行标志位 | - |
5-8 | 节点名 | - |
9-20 | Fx | kN |
21-32 | Fy | kN |
32-44 | Fz | kN |
45-56 | Mx | kNm |
57-68 | My | kNm |
69-80 | Mz | kNm |
END
END 代表时历载荷文件的结束,格式要求写在第1-3列上。
程序的数据结构
我们已经掌握了输入和输出数据文件的内容和格式,下面就以C#语言来进行编写程序。
首先,设计一个类来存储力的相关数据,其中包括三个方向的力和围绕三个坐标轴的力矩。
public class Force
{
public double Fx { get; set; }
public double Fy { get; set; }
public double Fz { get; set; }
public double Mx { get; set; }
public double My { get; set; }
public double Mz { get; set; }
public Force() { }
public Force(double fx, double fy, double fz, double mx, double my, double mz)
{
this.Fx = fx;
this.Fy = fy;
this.Fz = fz;
this.Mx = mx;
this.My = my;
this.Mz = mz;
}
}
这个类我们在以后SACS相关二次开发中也会经常用到。
时历载荷数据是由时间点和载荷组成的,接下来设计另一个类存储这一组数据。
public class TimePointForce
{
public double Time { get; set; }
public Force Force { get; set; }
public TimePointForce(double time, Force force)
{
this.Time = time;
this.Force = force;
}
}
另外,我们也需要一些辅助方法,来对用字符串表示的数据行进行处理。这里采用C#中扩展方法(Extensions)的技术。
public static class Extensions
{
public static string[] SpaceSplit(this string txt)
{
var parameters = txt.Split(new char[] {' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
return parameters;
}
public static string ToExponentialText(this double value, int decimals, int exponentDigits = 2)
{
var format = $@"0.{new String('0', decimals)}E+{new String('0', exponentDigits)}";
return value.ToString(format);
}
}
程序代码没有必要在这里全部贴出来,具体的思路如下:
- 将风机厂商提供的时历载荷文件中的所有行都读入到一个字符串列表中
- 从字符串列表的第4个元素开始,遍历解析每一行数据,生成TimePointFoce实例,并存入列表,直到最后一行
- 在指定路径下新建一个文本格式的SACS时历载荷文件
- 在SACS时历载荷文件的第1行写入THLOAD数据
- 遍历TimePointForce列表,对每一个元素,写入一行TIME数据,并紧接着写入一行JLOD数据
- 在最后一行,写入END数据行
为了方便使用,我设计了一个简单的用户界面。
总结
整个程序分开来看,每一部分对于对应的专业人士都是很简单的。
- 对于风机时历载荷数据的提供者,其文件格式自然掌握
- 对于精通SACS的设计分析工程师,SACS的时历载荷数据格式也可以通过查阅用户文档得到
- 文件的读写和用户界面的设计对于一个软件工程师来说则更是小菜一碟
但能够将各学科、专业和领域的相关知识集成在一起,并将程序编写、运行成功就稍有难度了。
目前,程序只是处理单个文件的转换,通过遍历指定目录下的所有时历载荷文件,实现批量转换将十分直接和简单。
同事对程序运行的结果很满意,为这个小项目划上了一个圆满的句号。