自动化仿真工具二次开发研究
发表时间:2023-09-15 10:00:44
文章来源:炫佑科技
浏览次数:166
菏泽炫佑科技
自动化仿真工具二次开发研究
基于自动化仿真工具的研究
1 简介
它是一套功能强大的工程模拟有限元软件,可以解决从相对简单的线性分析到许多复杂的非线性问题。 为了提高模拟效率,小编对公司二次开发进行了研究。 基于批量处理技术,开发了某装置的自动化仿真工具,进行了仿真模型的参数化建立、自动装配、自动网格划分、自动加荷等功能。 、自动添加边界条件、自动提取仿真结果和自动生成仿真报告,*终基于其开发出无人值守、全自动、快速的专家仿真工具。
2 二次开发 2.1 简介
它是一套功能强大的工程模拟有限元软件,可以解决从相对简单的线性分析到许多复杂的非线性问题。 包括丰富的元素库,可以模拟任意几何形状。 它还拥有各类材料模型库,可以模拟典型工程材料的性能,包括金属、橡胶、高分子材料、复合材料、钢筋混凝土、可压缩超弹性泡沫材料以及土壤和岩石等地质材料。 作为通用模拟工具自动化软件开发,除了解决大量结构(应力/位移)问题外,还可以模拟其他工程领域的许多问题,如热传导、质量扩散、热电耦合分析、声学分析、地质力学分析等(流体渗透/应力耦合分析)和压电介质分析。
2.2 开发语言
从CAE软件二次开发的角度来看,它是一款非常容易开发的软件,不像ANSYS等其他CAE软件。 运行时会自动生成大部分操作语言的.rpy操作日志文件。 该文件一般位于以下路径。
\SIMULIA\Temp
该文件是二次开发的有力武器。 为了熟悉指定操作对应的脚本,需要查看该操作的每一步的文件中对应的脚本。
当提到二次开发所使用的编程语言时,很多同学可能会被吓到。 毕竟从事这个软件开发的人大部分都是非计算机专业的。 小编在这里想给大家一颗定心丸。 仅仅因为你不懂编程并不意味着你不能开发。 使用的语句基本上是在软件内定义的。 你可以把它理解为一种标记语言。 只要能够将具体的脚本与相应的操作相匹配,就可以实现二次开发。
综上所述,编程语言是二次开发,只要了解记录操作的.rpy文件就可以进行。
3 关键技术 3.1 预处理脚本实现
预处理包括参数化建模、自动网格划分、添加约束载荷等。下面是我封装的一个脚本,用于参数化建模、装配模型、网格划分、添加约束载荷和添加分析步骤。 我将逐步解释它们,然后检查 .rpy 文件生成的相应脚本。 。 虽然过程很辛苦,但是效果还是不错的。
def parametric_modeling():
p = mdb.models['Model-1'].parts['Part-1']
session.viewports['Viewport: 1'].setValues(displayedObject=p)
p = mdb.models['Model-1'].parts['Part-1']
s = p.features['Shell planar-1'].sketch
mdb.models['Model-1'].ConstrainedSketch(name='__edit__', objectToCopy=s)
s1 = mdb.models['Model-1'].sketches['__edit__']
g, v, d, c = s1.geometry, s1.vertices, s1.dimensions, s1.constraints
s1.setPrimaryObject(option=SUPERIMPOSE)
p.projectReferencesOntoSketch(sketch=s1,upToFeature=p.features['Shell planar-1'], filter=COPLANAR_EDGES)
#--------------------删除旧约束------------------------------------
s1.delete(objectList=(d[1],))
s1.delete(objectList=(d[0],))
s1.delete(objectList=(d[3],))
s1.delete(objectList=(d[4],))
s1.delete(objectList=(d[2],))
s1.delete(objectList=(d[5],))
s1.delete(objectList=(d[13],))
s1.delete(objectList=(d[6],))
s1.delete(objectList=(d[7],))
s1.delete(objectList=(d[8],))
s1.delete(objectList=(d[9],))
s1.delete(objectList=(d[10],))
s1.delete(objectList=(d[11],))
s1.delete(objectList=(d[12],))
#--------------------添加新的约束------------------------------------
s1.RadialDimension(curve=g[4], textPoint=(123.286316143786, 0.258663984079395), radius=simuinfo[""]["R4"]["value"] )
s1.DistanceDimension(entity1=v[2], entity2=g[2], textPoint=(69.2119979858398, -14.4988307952881), value=simuinfo[""]["Distan1"]["value"])
s1.RadialDimension(curve=g[5], textPoint=(119.733726501465, 1.4805303812027), radius=simuinfo[""]["R3"]["value"])
s1.HorizontalDimension(vertex1=v[5], vertex2=v[2], textPoint=(122.07674407959, -0.124851405620575), value=simuinfo[""]["h1"]["value"])
s1.VerticalDimension(vertex1=v[5], vertex2=v[2], textPoint=(120.597770690918, 0.413793683052063), value=simuinfo[""]["h2"]["value"])
s1.DistanceDimension(entity1=g[7], entity2=g[3], textPoint=(126.956832885742, 0.931050896644592), value=simuinfo[""]["H"]["value"])
s1.RadialDimension(curve=g[8], textPoint=(123.122192382813, 2.98901391029358), radius=simuinfo[""]["R1"]["value"])
s1.RadialDimension(curve=g[9], textPoint=(121.781723022461, 2.07928419113159), radius=simuinfo[""]["R2"]["value"])
s1.AngularDimension(line1=g[10], line2=g[11], textPoint=(122.132789611816, 2.32126188278198), value=simuinfo[""]["jiao1"]["value"])
s1.DistanceDimension(entity1=g[13], entity2=g[6], textPoint=(120.765113830566, 0.700745701789856), value=simuinfo[""]["t"]["value"])
s1.AngularDimension(line1=g[17], line2=g[7], textPoint=(124.364456176758, 2.09015274047852), value=simuinfo[""]["jiao2"]["value"])
s1.RadialDimension(curve=g[18], textPoint=(123.774154663086, 2.06717729568481), radius=simuinfo[""]["c1"]["value"])
s1.RadialDimension(curve=g[19], textPoint=(123.522178649902, 1.81678450107574), radius=simuinfo[""]["c2"]["value"])
s1.DistanceDimension(entity1=v[5], entity2=g[20], textPoint=(123.31396484375, 1.17441308498383), value=simuinfo[""]["h"]["value"])
#--------------------------特征重新生成-----------------------------------------------------------------------
s1.unsetPrimaryObject()
p = mdb.models['Model-1'].parts['Part-1']
p.features['Shell planar-1'].setValues(sketch=s1)
del mdb.models['Model-1'].sketches['__edit__']
p = mdb.models['Model-1'].parts['Part-1']
p.regenerate()
#-------------------------------------------------------------------------------------------
p1 = mdb.models['Model-1'].parts['Part-2']
session.viewports['Viewport: 1'].setValues(displayedObject=p1)
p = mdb.models['Model-1'].parts['Part-2']
s = p.features['Shell planar-1'].sketch
mdb.models['Model-1'].ConstrainedSketch(name='__edit__', objectToCopy=s)
s2 = mdb.models['Model-1'].sketches['__edit__']
g, v, d, c = s2.geometry, s2.vertices, s2.dimensions, s2.constraints
s2.setPrimaryObject(option=SUPERIMPOSE)
p.projectReferencesOntoSketch(sketch=s2, upToFeature=p.features['Shell planar-1'], filter=COPLANAR_EDGES)
#--------------------------------删除旧约束----------------------------------------
s2.delete(objectList=(d[2],))#删除轴心距离
s2.delete(objectList=(d[3],))#删除环高
s2.delete(objectList=(d[1],))#删除块厚
s2.delete(objectList=(d[0],))#删除块宽
#-------------------------------添加新的约束------------------------------------------
s2.ObliqueDimension(vertex1=v[3], vertex2=v[0], textPoint=(122.24291229248, 5.57848644256592), value=simuinfo[""]["h1_yk"]["value"])
s2.ObliqueDimension(vertex1=v[0], vertex2=v[1], textPoint=(118.957969665527, 2.78910183906555), value=simuinfo[""]["t_yk"]["value"])
s2.DistanceDimension(entity1=g[6], entity2=g[2], textPoint=(32.0289764404297, 28.8339805603027), value=simuinfo[""]["distan"]["value"])#添加轴心距离
s2.DistanceDimension(entity1=g[5], entity2=g[3], textPoint=(128.655029296875, 1.35438060760498), value=simuinfo[""]["H_yk"]["value"])#添加环高度
#--------------------------------特征重新生成-------------------------------------------
s2.unsetPrimaryObject()
p = mdb.models['Model-1'].parts['Part-2']
p.features['Shell planar-1'].setValues(sketch=s2)
del mdb.models['Model-1'].sketches['__edit__']
p = mdb.models['Model-1'].parts['Part-2']
p.regenerate()
#----------创建材料---------------
def creat_material_and_section():
session.viewports['Viewport: 1'].partDisplay.setValues(sectionAssignments=ON, engineeringFeatures=ON)
session.viewports['Viewport: 1'].partDisplay.geometryOptions.setValues(referenceRepresentation=OFF)
#--------------------------创建两种材料---------------------------------
mdb.models['Model-1'].Material(name='Material-1')
mdb.models['Model-1'].materials['Material-1'].Elastic(table=((simuinfo["material_paras_dic"]["material1"]["yong_modulus"], simuinfo["material_paras_dic"]["material1"]["poisson_ratio"]),))
mdb.models['Model-1'].Material(name='Material-2')
mdb.models['Model-1'].materials['Material-2'].Elastic(table=((simuinfo["material_paras_dic"]["material2"]["yong_modulus"], simuinfo["material_paras_dic"]["material2"]["poisson_ratio"]),))
#---------------------------创建截面属性--------------------------------
mdb.models['Model-1'].HomogeneousSolidSection(name='Section-1', material='Material-1', thickness=None)
mdb.models['Model-1'].HomogeneousSolidSection(name='Section-2', material='Material-2', thickness=None)
#---------------------------指派截面属性--------------------------------
p = mdb.models['Model-1'].parts['Part-1']
session.viewports['Viewport: 1'].setValues(displayedObject=p)
p = mdb.models['Model-1'].parts['Part-1']
f = p.faces
faces = f.getSequenceFromMask(mask=('[#1 ]',), )
region = p.Set(faces=faces, name='Set-1')
p = mdb.models['Model-1'].parts['Part-1']
p.SectionAssignment(region=region, sectionName='Section-1', offset=0.0, offsetType=MIDDLE_SURFACE, offsetField='',
thicknessAssignment=FROM_SECTION)
p = mdb.models['Model-1'].parts['Part-2']
session.viewports['Viewport: 1'].setValues(displayedObject=p)
p = mdb.models['Model-1'].parts['Part-2']
f = p.faces
faces = f.getSequenceFromMask(mask=('[#1 ]',), )
region = p.Set(faces=faces, name='Set-1')
p = mdb.models['Model-1'].parts['Part-2']
p.SectionAssignment(region=region, sectionName='Section-2', offset=0.0, offsetType=MIDDLE_SURFACE, offsetField='',
thicknessAssignment=FROM_SECTION)
#------------装配函数----------------
def assemble_two_parts():
seemble_dis = simuinfo["fyh_paras_dic"]["H"]["value"]*2 + simuinfo["yk_paras_dic"]["t_yk"]["value"]
a = mdb.models['Model-1'].rootAssembly
session.viewports['Viewport: 1'].setValues(displayedObject=a)
session.viewports['Viewport: 1'].assemblyDisplay.setValues(optimizationTasks=OFF, geometricRestrictions=OFF,
stopConditions=OFF)
a = mdb.models['Model-1'].rootAssembly
a.DatumCsysByThreePoints(coordSysType=CYLINDRICAL, origin=(0.0, 0.0, 0.0),
point1=(1.0, 0.0, 0.0), point2=(0.0, 0.0, -1.0))
p = mdb.models['Model-1'].parts['Part-1']
a.Instance(name='Part-1-1', part=p, dependent=ON)
a = mdb.models['Model-1'].rootAssembly
p = mdb.models['Model-1'].parts['Part-2']
a.Instance(name='Part-2-1', part=p, dependent=ON)
a = mdb.models['Model-1'].rootAssembly
a.LinearInstancePattern(instanceList=('Part-2-1',), direction1=(1.0, 0.0, 0.0), direction2=(0.0, -1.0, 0.0),
number1=1, number2=2, spacing1=2.92, spacing2=seemble_dis)
#--------创建分析步-------------------
def creat_step():
session.viewports['Viewport: 1'].assemblyDisplay.setValues(adaptiveMeshConstraints=ON)
mdb.models['Model-1'].StaticStep(name='Step-1', previous='Initial', maxNumInc=simuinfo["analysis_paras_dic"]["0"]["vale"])
session.viewports['Viewport: 1'].assemblyDisplay.setValues(step='Step-1')
mdb.models['Model-1'].FieldOutputRequest(name='F-Output-2', createStepName='Step-1', variables=('RT',))
#--------创建相互接触---------------
def creat_intertact():
session.viewports['Viewport: 1'].assemblyDisplay.setValues(interactions=ON, constraints=ON, connectors=ON,
engineeringFeatures=ON, adaptiveMeshConstraints=OFF)
mdb.models['Model-1'].ContactProperty('IntProp-1')
mdb.models['Model-1'].interactionProperties['IntProp-1'].TangentialBehavior(
formulation=PENALTY, directionality=ISOTROPIC, slipRateDependency=OFF,
pressureDependency=OFF, temperatureDependency=OFF, dependencies=0, table=((
simuinfo["analysis_paras_dic"]["1"]["vale"],),), shearStressLimit=None, maximumElasticSlip=FRACTION, fraction=0.005, elasticSlipStiffness=None)
a = mdb.models['Model-1'].rootAssembly
s1 = a.instances['Part-2-1'].edges
side1Edges1 = s1.getSequenceFromMask(mask=('[#4 ]',), )
region1 = a.Surface(side1Edges=side1Edges1, name='m_Surf-1')
a = mdb.models['Model-1'].rootAssembly
s1 = a.instances['Part-1-1'].edges
side1Edges1 = s1.getSequenceFromMask(mask=('[#200000 ]',), )
region2 = a.Surface(side1Edges=side1Edges1, name='s_Surf-1')
mdb.models['Model-1'].SurfaceToSurfaceContactStd(name='Int-1',
createStepName='Step-1', master=region1, slave=region2,
sliding=FINITE,
thickness=ON, interactionProperty='IntProp-1', adjustMethod=NONE,
initialClearance=OMIT, datumAxis=None, clearanceRegion=None)
a = mdb.models['Model-1'].rootAssembly
s1 = a.instances['Part-2-1-lin-1-2'].edges
side1Edges1 = s1.getSequenceFromMask(mask=('[#1 ]',), )
region1 = a.Surface(side1Edges=side1Edges1, name='m_Surf-3')
a = mdb.models['Model-1'].rootAssembly
s1 = a.instances['Part-1-1'].edges
side1Edges1 = s1.getSequenceFromMask(mask=('[#10 ]',), )
region2 = a.Surface(side1Edges=side1Edges1, name='s_Surf-3')
mdb.models['Model-1'].SurfaceToSurfaceContactStd(name='Int-2',
createStepName='Step-1', master=region1, slave=region2,
sliding=FINITE,
thickness=ON, interactionProperty='IntProp-1', adjustMethod=NONE,
initialClearance=OMIT, datumAxis=None, clearanceRegion=None)
#---------创建载荷------------------
def creat_load():
session.viewports['Viewport: 1'].assemblyDisplay.setValues(loads=ON, bcs=ON,
predefinedFields=ON, interactions=OFF, constraints=OFF,
engineeringFeatures=OFF)
a = mdb.models['Model-1'].rootAssembly
e1 = a.instances['Part-2-1-lin-1-2'].edges
edges1 = e1.getSequenceFromMask(mask=('[#4 ]',), )
region = a.Set(edges=edges1, name='Set-1')
mdb.models['Model-1'].EncastreBC(name='BC-1', createStepName='Step-1',
region=region, localCsys=None)
a = mdb.models['Model-1'].rootAssembly
e1 = a.instances['Part-2-1'].edges
edges1 = e1.getSequenceFromMask(mask=('[#1 ]',), )
region = a.Set(edges=edges1, name='Set-2')
mdb.models['Model-1'].DisplacementBC(name='BC-2', createStepName='Step-1',
region=region, u1=0.0, u2=simuinfo["analysis_paras_dic"]["2"]["vale"], ur3=0.0, amplitude=UNSET, fixed=OFF,
distributionType=UNIFORM, fieldName='', localCsys=None)
#---------网格划分------------------
def generate_mesh():
session.viewports['Viewport: 1'].assemblyDisplay.setValues(mesh=ON, loads=OFF,
bcs=OFF, predefinedFields=OFF, connectors=OFF)
session.viewports['Viewport: 1'].assemblyDisplay.meshOptions.setValues(
meshTechnique=ON)
p = mdb.models['Model-1'].parts['Part-1']
session.viewports['Viewport: 1'].setValues(displayedObject=p)
p = mdb.models['Model-1'].parts['Part-1']
p.seedPart(size=simuinfo["analysis_paras_dic"]["3"]["vale"], deviationFactor=0.1, minSizeFactor=0.1)
p = mdb.models['Model-1'].parts['Part-1']
p.generateMesh()
p = mdb.models['Model-1'].parts['Part-2']
session.viewports['Viewport: 1'].setValues(displayedObject=p)
p = mdb.models['Model-1'].parts['Part-2']
p.seedPart(size=simuinfo["analysis_paras_dic"]["4"]["vale"], deviationFactor=0.1, minSizeFactor=0.1)
p = mdb.models['Model-1'].parts['Part-2']
p.generateMesh()
3.2 模拟作业提交
提交模拟作业没有什么难度,按照同样的方法即可。 我立刻想到了强大的工具.rpy日志脚本。 以下是.rpy文件中获取的作业提交脚本。
a1 = mdb.models['Model-1'].rootAssembly
a1.regenerate()
a = mdb.models['Model-1'].rootAssembly
session.viewports['Viewport: 1'].setValues(displayedObject=a)
session.viewports['Viewport: 1'].assemblyDisplay.setValues(mesh=OFF)
session.viewports['Viewport: 1'].assemblyDisplay.meshOptions.setValues(
meshTechnique=OFF)
mdb.Job(name='Job-1', model='Model-1', description='', type=ANALYSIS,
atTime=None, waitMinutes=0, waitHours=0, queue=None, memory=90,
memoryUnits=PERCENTAGE, getMemoryFromAnalysis=True,
explicitPrecision=SINGLE, nodalOutputPrecision=SINGLE, echoPrint=OFF,
modelPrint=OFF, contactPrint=OFF, historyPrint=OFF, userSubroutine='',
scratch='', resultsFormat=ODB, multiprocessingMode=DEFAULT, numCpus=5,
numDomains=simuinfo["job_para_dic"]["8"]["value"], numGPUs=simuinfo["job_para_dic"]["9"]["value"])
3.3 后处理实现
通过 中的脚本可以完成很多操作,比如获取某个云图的极值数据,将云图导出到指定路径,提取指定节点的应力、位移、支撑反力等。还可以获取节点的坐标。 下图展示了后处理部分的命名空间。 *外层对象是odb模拟结果对象,通过该对象可以获得指定部位各节点的坐标; 通过步骤,可以获得现场输出信息,如支援反作用力等。 以上每个功能都是我自己开发实现的自动化仿真工具二次开发研究,并且经过亲自测试有效。 下面附上我研究的导出云镜像的脚本。 首先调整云图的视角,然后将云图导出到指定路径。
session.viewports['Viewport: 1'].view.fitView()
session.printOptions.setValues(vpDecorations=OFF, vpBackground=ON)
session.printToFile(fileName=simu_instance_path + '/pic_rt', format=PNG,
canvasObjects=(session.viewports['Viewport: 1'],))
4 调度工具开发
上一节解释了如何探索中的脚本并开发我们关心的功能。 下面介绍如何通过批处理实现自动化仿真。 拥有这些脚本是开发自动模拟工具的**步。 还需要开发仿真作业调度和管理工具。 该工具实现外部调用执行脚本,自动调度仿真作业,并在仿真完成后分析仿真结果生成仿真报告。
4.1 外部调用
外部调用是通过命令行参数实现的。 调用时传入控制批处理的参数和要执行的脚本文件,即可实现批处理模式模拟。
4.2 模拟作业调度
所谓仿真作业调度,是指用户可以添加多个仿真,然后软件负责对仿真进行逐一调度,直至所有仿真完成,实现“无人值守”的仿真。
4.3 仿真报告生成
基于word二次开发实现模拟报告生成。 系统对仿真得到的仿真数据和云图进行分析,结合word仿真报告模板,快速生成某次仿真的仿真报告模板。
//------------------------------------------------承接CAD/CAE软件二次开发-------------------------------------------------------- ----- ----------------------------------
我们有着强大的二次开发团队,常年从事CAD/CAE软件二次开发工作。已经开发过UG/CATIA等CAD软件,近年来又攻坚克难攻克了CAE软件ansy /workbench/abaqus的二次开发工作。
希望广大有兴趣的朋友交流咨询二次开发技术,欢迎有需求的客户咨询二次开发业务。
邮箱:zwp_154979@163.com
一支致力于让专业化软件更加人性化的倔强团队!!!
//------------------------------------------------ -------------------------------------------------- -------------------------------------------------- -------------