仿真脚本发展现状

脚本语言相关:由于Python编程语言发展较晚,此前自动化等脚本都是VBA,例如CST/HFSS/AWR/ANSYS/ABAQUS/Excel等软件现在仍保留着这些接口。但是VB的弊端很明显,语法不够简单、灵活性有限。因此可以看到和预料到近年以及后续会有越来越多的软件适配Python接口。(笔者4年前也是感觉有此趋势所以在那个时候就开始学习Python了)

脚本二次开发常见适用领域:

CAD二次开发。例如autoCad,Creo等CAD软件。由于目前各行各业使用CAD+CAE的比例越来越高,水平越来越好,模型/业务越复杂,自动化CAD建模会有越来越大的需求。目前市场需求稍微多一点的是AutoCad自动建模。

CAE二次开发。如电磁/流体/光学/力学仿真等。CAE往往需要建模+剖分+计算,因此CAE可以做的地方更多。大致大家就分为了前处理+后处理+自动优化等。目前市场需求较大的是自动MESH和后处理。
总之,就一句话,人生苦短,请用Python。

学习建议

Python语言相关

  1. 基础语法。这个就不用多说了。
  2. Python相关的库。建议学习numpy,pandas这2个数据处理的库,matplotlib绘图库,如xlwt等Excel文件处理相关的库,最后就是pyqt5写GUI界面的库。

仿真软件相关

  1. 仿真的基本过程。仿真软件的运行和使用过程。不需要很会建模啊,搞设计,但是呢,软件怎么运行的,大致的按钮,每个功能是什么这些必须得会。这一块建议多学学,能否做一个好的软件,软件使用水平很重要。怎么建模,怎么简化模型,怎么设置材料库,怎么mesh,怎么设置边界,怎么设置激励,怎么建立仿真sutup,怎么获取数据等等。
  2. 脚本相关的文档。查看对应CAE软件的script脚本文档,里面会清楚地告知怎么调用每个接口,函数参数等。部分好一点的商业软件还内置了录制脚本的功能,这个非常非常实用。
    这块需要不断的学习,笔者也只学了ANSYS/CST/ABAQUS的目前。

HFSS自动化实例

脚本开发目的:能自动化设置激励,自动化导出结果,最终形成一个汇总指标单。

界面开发:由于是脚本,所以需要在仿真的服务器或者是PC上运行,自动和程序交互,所以需要编写一个GUI程序界面。

python二次开发jmeter python二次开发creo_自动化


pyqt编写的,具体怎么写这个界面,搭建可以自行百度,用designer即可拖拽形成界面。界面几个模块主要是仿真文件的对应参数,不同行业肯定不一样,所以就不赘述了。

总体思路是:程序自动打开HFSS软件,自动根据激励文件输入激励并输出结果。这个代码太长所以就不放上面了。

更改激励脚本:

def get_excitions(Am, Ph, array, sum):
    array=[int(i) for i in array]
    home_list = [["IncludePortPostProcessing:=", True,
                  "SpecifySystemPower:=", False]]
    for i in range(1, sum + 1):
        if i in array:
            name = str(i)
            am = str(Am[array.index(i)]) + "W"
            phase = str(Ph[array.index(i)])
            part = [
                "Name:=", name,
                "Magnitude:=", am,
                "Phase:=", phase]
        else:
            name = str(i)
            part = [
                "Name:=", name,
                "Magnitude:=", "0W",
                "Phase:=", "0deg"]
        home_list.append(part)

    return home_list

通过此函数可以安装幅度相位数据自动生成相应的激励代码,输出的home_list即HFSS可以识别的更改激励的设置。
(具体的里面每个参数建议录制脚本参考)

抽取结果并导出为CSV文件代码:

从3D数据里面抽取结果,s参数,2D方向图等,此脚本是2D方向图数据。

def generate_report(xiaqing, oDesign, outcom_path, setup_name, radiation, port_num):
    oModule = oDesign.GetModule("ReportSetup")
    # 垂直面
    V_name = "T" + str(xiaqing) + "_V"
    oModule.CreateReport(V_name, "Far Fields", "Rectangular Plot", setup_name,
                         [
                             "Context:=", radiation
                         ],
                         [
                             "Theta:=", ["All"],
                             "Phi:=", ["0deg"],
                             "Freq:=", ["All"],
                         ],
                         [
                             "X Component:=", "Theta",
                             "Y Component:=", ["dB(GainTotal)"]
                         ], [])
    # 水平面
    H_name = "T" + str(xiaqing) + "_H"
    theta = str(90 + int(xiaqing)) + "deg"
    print(H_name, theta)
    oModule.CreateReport(H_name, "Far Fields", "Rectangular Plot", setup_name,
                         ["Context:=", radiation],
                         [
                             "Phi:=", ["All"],
                             "Theta:=", [theta],
                             "Freq:=", ["All"],
                         ],
                         [
                             "X Component:=", "Phi",
                             "Y Component:=", ["dB20(co1)", "dB20(cro1)"]
                         ], [])
    oModule.AddTraces(H_name, setup_name,
                      ["Context:=", radiation],
                      [
                          "Phi:=", ["All"],
                          "Theta:=", [theta],
                          "Freq:=", ["All"],
                      ],
                      [
                          "X Component:=", "Phi",
                          "Y Component:=", ["dB(GainTotal)"]
                      ], [])
    # 建结果文件夹
    path = outcom_path + "/PORT" + str(port_num)
    H = path + "/T" + str(xiaqing) + "_H.csv"
    V = path + "/T" + str(xiaqing) + "_V.csv"
    if not os.path.exists(path):
        os.makedirs(path)
    oModule.ExportToFile(H_name, H)
    oModule.ExportToFile(V_name, V)
    oModule.DeleteReports([H_name, V_name])

注:里面涉及到一些3D数据构成和方向图知识,非电磁专业的工程师可能不理解。

汇总成Excel代码:

将导出的CSV 方向图文件进行计算,并形成报告。

# 解析水平面数据并保存图片
def parse(datas, name, temp_dirs):
    columns = datas.columns.values.tolist()  # 获取列名列表,注意values,tolist的使用
    theta = datas[columns[0]].values.tolist()
    empty = pd.DataFrame(
        columns=['PORT&T', '频点', '水平面增益Gain', '水平面波宽(3dB)', '水平面波宽(10dB)', '主极化前后比', '交叉极化前后比', '交叉极化比(0°)'
            , '交叉极化比(±60°)', '水平面波束偏移(最大值)','水平面波束偏移(3dB)', '+60°边缘功率下降', '-60°边缘功率下降',"总功率前后比(±15°)","总功率前后比(±30°)","总功率前后比(±180°)"])
    fig = plt.figure()
    for column in columns[1:]:
        freq = float(re.findall(".*?Freq='(.*?)GHz.*?'", column)[0]) * 1000
        if 'co1' in column:
            data1 = datas[column].values.tolist()  # 主极化
            column2 = column.replace('co1', 'cro1')
            data2 = datas[column2].values.tolist()  # 交叉极化
            if max(data1) < max(data2):
                data3 = data2
                data2 = data1
                data1 = data3
            new_column = column.replace("dB20(co1)", "dB(GainTotal)")
            db_data=datas[new_column].values.tolist()
            gain_total = max(db_data)
            max_value = max(data1)  # 最大值
            db3kokuan = calc1(theta, data1)  # 3db波宽
            db10kokuan = calc2(theta, data1)  # 10db波宽
            mainqianhou = calc3(theta, data1)  # 主极化前后比
            croqianhou = calc4(theta, data1, data2)  # 交叉极化前后比
            cro0 = calc5(theta, data1, data2)  # 0°交叉极化比
            cro60 = calc6(theta, data1, data2)  # 60°交叉极化比
            dis = calc7(theta, data1)  # 水平波束偏移
            dis_3 = calc9(theta, data1, 3)  # 水平波束偏移(3db)
            down60_1, down60_2 = calc8(theta, data1)  # +-60°边缘功率下降
            total_qianhou_15, total_qianhou_30, total_qianhou_180 = calc10(theta, db_data, 15), calc10(theta, db_data,30), calc10(theta,db_data,180)
            a = pd.Series(
                {'PORT&T': name, '频点': freq, '水平面增益Gain': gain_total, '水平面波宽(3dB)': db3kokuan, '水平面波宽(10dB)': db10kokuan,
                 '主极化前后比': mainqianhou, '交叉极化前后比': croqianhou, '交叉极化比(0°)': cro0
                    , '交叉极化比(±60°)': cro60, '水平面波束偏移(最大值)': dis, '水平面波束偏移(3dB)': dis_3, '+60°边缘功率下降': down60_1,
                 '-60°边缘功率下降': down60_2, "总功率前后比(±15°)": total_qianhou_15, "总功率前后比(±30°)": total_qianhou_30,
                 "总功率前后比(±180°)": total_qianhou_180})
            # empty.append([{'PORT&T':name,'频点':freq,'水平面增益Gain':max_value,'水平面波宽(3dB)':db3kokuan,'水平面波宽(10dB)':db10kokuan,'主极化前后比':mainqianhou,'交叉极化前后比':croqianhou,'交叉极化比(0°)':cro0
            #                      ,'交叉极化比(±60°)':cro60,'水平面波束偏移':dis,'+60°边缘功率下降':down60_1,'-60°边缘功率下降':down60_2}], ignore_index=True)
            empty = empty.append(a, ignore_index=True)
            plt.plot(theta, data1)
            plt.plot(theta, data2)
    plt.grid()
    plt.title(name)
    plt.xlabel("Phi", fontsize=16)
    plt.ylabel("db", fontsize=16)
    # plt.show()
    fig.savefig(temp_dirs + name + "_H.jpg")
    print(empty.isna().sum())
    return empty

此例子是计算了一个水平面方向图数据并汇总成pandas数据,还生成了相应数据图片

最后

再将以上模块用主程序和循环控制,即完成了整个程序。下面是程序运行的过程样例和结果。


HFSS后处理样例


结语

该帖主要讲述了大致的学习、发展方向和开发思路,样例也仅提供了一个较成熟的后处理例子,由于结构较复杂涉及知识点略多,所以基础未讲太基础的部分(基础部分其余博客都讲比较多)。后续会再增加CST和Abaqus较基础的自动化程序样例。
注:所有程序均为自主开发,如对内容有疑问,请私信联系我。