Skip to content

Module for co-simulation with Ansys Workbench using Python

Notifications You must be signed in to change notification settings

ansys-dev/PyWbUnit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 

Repository files navigation

PyWbUnit

本模块提供Python与Workbench联合仿真的支持:可通过Python启动Workbench,并向WB实时发送脚本代码执行,同时支持查询代码执行结果和脚本变量值。

说明:本模块只提供Python与Workbench中的ScriptEngine的双向数据接口,WB中仿真功能实现还需要通过其Python脚本开发实现,可以参考以下文章:

安装使用

预编译的二进制库目前只支持Windows x64平台的Python3.7、3.8、3.9版本,安装方法如下:

pip install PyWbUnit-0.3.0-cp37-none-win_amd64.whl
pip install PyWbUnit-0.3.0-cp38-none-win_amd64.whl
pip install PyWbUnit-0.3.0-cp39-none-win_amd64.whl

API说明

Help on class CoWbUnitProcess in module PyWbUnit._CoWbUnit:

class CoWbUnitProcess(builtins.object)
 |  
 |  CoWbUnitProcess(workDir=None, version=201, interactive=True)
 |
 |  Unit class for co-simulation with Workbench using Python.
 |
 |  >>> coWbUnit = CoWbUnitProcess()
 |  >>> coWbUnit.initialize()
 |  >>> command = 'GetTemplate(TemplateName="Static Structural", Solver="ANSYS").CreateSystem()'
 |  >>> coWbUnit.execWbCommand(command)
 |  >>> coWbUnit.execWbCommand('systems=GetAllSystems()')
 |  >>> print(coWbUnit.queryWbVariable('systems'))
 |  >>> coWbUnit.saveProject(r'D:/example.wbpj')
 |  >>> coWbUnit.finalize()
 |
 |  Methods defined here:
 |
 |  __init__(self, workDir=None, version=201, interactive=True)
 |      Constructor of CoWbUnitProcess.
 |      :param workDir: str, the directory where the Workbench starts.
 |      :param version: int, workbench version: 2019R1-190/2020R1-201/2021R1-211.
 |      :param interactive: bool, whether to display the Workbench interface
 |
 |  execWbCommand(self, command: 'str') -> 'str'
 |      Send python script command to the Workbench for execution
 |      :param command: str, python script command
 |      :return: str, execution result
 |
 |  exitWb(self) -> 'str'
 |      `Exit` the current Workbench client process and close the Workbench server
 |      :return: str
 |
 |  finalize(self)
 |      Exit the current workbench and close the TCP Server connection
 |      :return: None
 |
 |  initialize(self) -> None
 |      Called before `execWbCommand`: Start the Workbench in the server
 |      mode and open the TCP server port to create a socket connection
 |      :return: None
 |
 |  queryWbVariable(self, variable: 'str')
 |      Query the value of `variable` in the workbench script environment
 |      :param variable: str, script variable name
 |      :return: str
 |
 |  saveProject(self, filePath=None, overWrite=True)
 |      Save the current workbench project file to `filePath`
 |      If the Project has not been saved, using method: `saveProject()`
 |      will raise `CommandFailedException`
 |      :param filePath: Optional[str, None], if
 |      :param overWrite: bool, Whether to overwrite the original project
 |      :return: str, execution result
 |
 |  terminate(self)
 |      Terminates the current Workbench client process
 |      :return: bool
 |
 |  ----------------------------------------------------------------------
 
Help on class WbServerClient in module PyWbUnit._CoWbUnit:

class WbServerClient(builtins.object)
 |
 |  WbServerClient(aasKey: 'str')
 |
 |  Client Class for the Workbench server connection
 |  >>> aas_key = 'localhost:9000'
 |  >>> wbClient = WbServerClient(aas_key)
 |  >>> wbClient.execWbCommand('<wb_python_command>')
 |  >>> print(wbClient.queryWbVariable('<wb_python_var>'))
 |
 |  Methods defined here:
 |
 |  __init__(self, aasKey: 'str')
 |
 |  execWbCommand(self, command: 'str') -> 'str'
 |
 |  queryWbVariable(self, variable) -> 'str'
 |
 |  ----------------------------------------------------------------------

核心类实现

# -*- coding: utf-8 -*-
from socket import *

class WbServerClient:

    _suffix = '<EOF>'
    _coding = 'US-ASCII'
    _buffer = 1024

    def __init__(self, aasKey: str):
        aasList = aasKey.split(':')
        self._address = (aasList[0], int(aasList[1]))

    def execWbCommand(self, command: str) -> str:
        sockCommand = command + self._suffix
        with socket(AF_INET, SOCK_STREAM) as sock:
            sock.connect(self._address)
            sock.sendall(sockCommand.encode(self._coding))
            data = sock.recv(self._buffer).decode()
        return data

    def queryWbVariable(self, variable) -> str:
        self.execWbCommand("__variable__=" + variable + ".__repr__()")
        retValue = self.execWbCommand("Query,__variable__")
        return retValue[13:]

使用方法

首先从PyWbUnit模块中导入CoWbUnitProcess类,详细文档说明可以通过help(CoWbUnitProcess)查看,以公众号文章:《ANSYS中使用Python实现高效结构仿真》为例,演示如何使用PyWbUnit调用Workbench完成联合仿真的过程:

# -*- coding: utf-8 -*-
from PyWbUnit import CoWbUnitProcess

# 创建wb单元实例,指定ansys wb版本,如2020R1对应201
coWbUnit = CoWbUnitProcess(workDir=r'E:/Workdata', version=201, interactive=True)
coWbUnit.initialize()
command = 'mechSys = GetTemplate(TemplateName="Static Structural", Solver="ANSYS").CreateSystem()'
coWbUnit.execWbCommand(command)
coWbUnit.execWbCommand('systems=GetAllSystems()')
print(coWbUnit.queryWbVariable('systems'))
materialScript = r'''# 创建静结构分析流程
# 获得Engineering Data数据容器
engData = mechSys.GetContainer(ComponentName="Engineering Data")
# 封装创建材料的方法
def CreateMaterial(name, density, *elastic):
    mat = engData.CreateMaterial(Name=name)
    mat.CreateProperty(Name="Density").SetData(Variables=["Density"],
        Values=[["%s [kg m^-3]" % density]])
    elasticProp = mat.CreateProperty(Name="Elasticity", Behavior="Isotropic")
    elasticProp.SetData(Variables=["Young's Modulus"], Values=[["%s [MPa]" % elastic[0]]])
    elasticProp.SetData(Variables=["Poisson's Ratio"], Values=[["%s" % elastic[1]]])
# 创建材料Steel,密度:7850kg/m3,杨氏模量:208e3MPa,泊松比:0.3
CreateMaterial("Steel", 7850, 209.e3, 0.3)'''
coWbUnit.execWbCommand(materialScript)
coWbUnit.execWbCommand('geo=mechSys.GetContainer("Geometry")')
coWbUnit.execWbCommand('geo.Edit(IsSpaceClaimGeometry=True)')
geoScript = r'''# Python Script, API Version = V18
# 创建悬臂梁实体区域
BlockBody.Create(Point.Origin, Point.Create(MM(200), MM(25), MM(20)))
GetRootPart().SetName("Beam")
# 选择beam实体,用于后续材料赋予
Selection.Create(GetRootPart().Bodies).CreateAGroup("ns_beamBody")
# 通过坐标点选择面对象
def GetFaceObjByPt(pt):
    for face in GetRootPart().GetDescendants[IDesignFace]():
        if face.Shape.ContainsPoint(pt): return face
# 选择固定约束加载面
fixSupFace = GetFaceObjByPt(Point.Create(0, MM(12.5), MM(10)))
Selection.Create(fixSupFace).CreateAGroup("ns_fixSup")
# 选择压力载荷加载面
pressFace = GetFaceObjByPt(Point.Create(MM(50), MM(12.5), MM(20)))
Selection.Create(pressFace).CreateAGroup("ns_press")
'''
coWbUnit.execWbCommand(f'geo.SendCommand(Language="Python", Command={geoScript!r})')
coWbUnit.execWbCommand(f'geo.Exit()')
launchScript = r'''# 刷新Model Component数据
modelComp = mechSys.GetComponent(Name="Model")
modelComp.Refresh()
# 获得Mechanical中Model的数据容器
model = mechSys.GetContainer(ComponentName="Model")
model.Edit()'''
coWbUnit.execWbCommand(launchScript)
mechScript = r"""# encoding: utf-8
# 给定Named Selection名称获取子对象实例
def GetLocByName(ns_name):
    for ns in Model.NamedSelections.Children:
        if ns.Name == ns_name: return ns
# 指定材料
matAss = Model.Materials.AddMaterialAssignment()
matAss.Material = "Steel"
matAss.Location = GetLocByName("ns_beamBody")
# 划分网格
mesh = Model.Mesh
mesh.ElementSize = Quantity("10 [mm]")
mesh.GenerateMesh()
# 获得Analyses对象
analysis = Model.Analyses[0]
# 添加固定约束
fixSup = analysis.AddFixedSupport()
fixSup.Location= GetLocByName("ns_fixSup")
# 加载压力载荷
pressLoad = analysis.AddPressure()
pressLoad.Location = GetLocByName("ns_press")
pressLoad.Magnitude.Output.DiscreteValues = [Quantity("0.5 [MPa]")]
Model.Solve()
# 后处理操作
solution = analysis.Solution
misesResult = solution.AddEquivalentStress()
misesResult.EvaluateAllResults()
# 设置视角
camera = ExtAPI.Graphics.Camera
camera.UpVector = Vector3D(0,0,1)
camera.SceneWidth = Quantity("150 [mm]")
camera.SceneHeight = Quantity("120 [mm]")
camera.FocalPoint = Point((0.08,0.0125,0), 'm')
# 输出后处理云图
misesResult.Activate()
ExtAPI.Graphics.ExportImage("d:/mises.png")"""
coWbUnit.execWbCommand(f'model.SendCommand(Language="Python", Command={mechScript!r})')
coWbUnit.execWbCommand('model.Exit()')
coWbUnit.saveProject(r"E:/Workdata/beam.wbpj")
# 关闭wb单元实例
coWbUnit.finalize()

问题反馈

关注微信公众号:“ANSYS仿真与开发”,后台留言;或者邮件至:[email protected]