Automation and iteration in Workbench
A customer had a request to make the number of design parameter sets dependent on the result of a solution. So I put together a few lines to do exactly that.
The script below can be run in Workbench.
It will iterate on the parameterized load (a simple force) until the given deflection parameter is reached. (as a control, a max ctr was also used).
So it starts, runs one analysis, then checks if the deflection criteria is met and if not goes into a loop to increase the force load by 10% until the criteria is satisfied.
Example Script:
Reset()
""" This script will create an iterative DP Ansys run"""
import tempfile, os tempdirectory = tempfile.gettempdir()
name = "myTest.wbpj"
saveName = os.path.join(tempdirectory,name) import time
t1 = time.time()
X = 1000
Y = 1000
Z = 1000
Load = 1000
fx = 'fixFace'
lx = 'loadFace' Some iteration parameters maxDef = 7E-06 # goal to cut out
deltaForcePercent = 1.1 # value to multiply myInput
maxctr = 10 # control for to avoid looping too long cmd = """
P0 = Point.Create(MM(0),MM(0),MM(0))
P1 = Point.Create(MM(%s),MM(%s),MM(%s))
BlockBody.Create(P0,P1)
"""%(X,Y,Z) myTemplate = GetTemplate(TemplateName="Static Structural",Solver="ANSYS")
mySystem = myTemplate.CreateSystem() geometry = mySystem.GetContainer(ComponentName="Geometry")
geometry.Edit(IsDiscoveryGeometry = True, Interactive = True)
geometry.SendCommand(Language="Python", Command=cmd)
geometry.Exit() modelContainer = mySystem.GetContainer(ComponentName="Model")
modelComponent = mySystem.GetComponent(Name="Model")
modelComponent.Update(AllDependencies=True) mechcmd = """ ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM Mesh M = ExtAPI.DataModel.Project.Model.Mesh
M.ElementSize = Quantity('500 [mm]')
M.CreateParameter('ElementSize') Fixed Support NS = Model.AddNamedSelection()
NS.ScopingMethod=GeometryDefineByType.Worksheet
NS.Name = "%s"
Criteria = NS.GenerationCriteria
Criteria.Add(None)
Criteria[0].EntityType = SelectionType.GeoFace
Criteria[0].Criterion = SelectionCriterionType.LocationY
Criteria[0].Operator = SelectionOperatorType.Equal
Criteria[0].Value = Quantity('0 [mm]')
NS.Generate() NS = Model.AddNamedSelection()
NS.ScopingMethod=GeometryDefineByType.Worksheet
NS.Name = "%s"
Criteria = NS.GenerationCriteria
Criteria.Add(None)
Criteria[0].EntityType = SelectionType.GeoFace
Criteria[0].Criterion = SelectionCriterionType.LocationY
Criteria[0].Operator = SelectionOperatorType.Equal
Criteria[0].Value = Quantity(str(%s) + ' [mm]')
NS.Generate()
F= Model.Analyses[0].AddForce()
F.Location = ExtAPI.DataModel.GetObjectsByName("%s")[0]
F.DefineBy = LoadDefineBy.Components
F.YComponent.Output.SetDiscreteValue(0, Quantity(%s, "N"))
F.CreateParameter('ComponentY') B = Model.Analyses[0].AddFixedSupport()
B.Location = ExtAPI.DataModel.GetObjectsByName("%s")[0] Add Result Total Deformation TD = ExtAPI.DataModel.Project.Model.Analyses[0].Solution.AddTotalDeformation()
TD.CreateParameter('Maximum')
"""%(fx,lx,Y,lx,Load,fx) modelContainer.SendCommand(Language="Python", Command=mechcmd)
modelContainer.Edit(Interactive=False)
t2 = time.time() designPoint1 = Parameters.GetDesignPoint(Name="0")
parameter1 = Parameters.GetParameter(Name="P1")
parameter2 = Parameters.GetParameter(Name="P2") Save(FilePath = saveName, Overwrite=True) print('time = ' + str(round(t2-t1,2))) iteration loop ##dp1 = Parameters.GetDesignPoint(Name="0")
myInputParameter = Parameters.GetParameter(Name="P2")#
myInputValue = myInputParameter.Value.Value
inputUnits = myInputParameter.Value.Unit newInputValue = deltaForcePercent*myInputValue
backgroundSession1 = UpdateAllDesignPoints(DesignPoints=[designPoint1])
myOutput = Parameters.GetParameter(Name="P3").Value.Value ctr = 0
while myOutput <= maxDef and ctr <= maxctr:
print('Deflection goal not reached, will iterate')
dpX = designPoint1.Duplicate()
Parameters.SetBaseDesignPoint(DesignPoint=dpX)
newInputQuantity = str(newInputValue) + ' [' + inputUnits+']'
print(newInputValue)
dpX.SetParameterExpression(Parameter=myInputParameter,Expression = newInputQuantity)
backgroundSession1 = UpdateAllDesignPoints(DesignPoints=[dpX])
myOutput = Parameters.GetParameter(Name="P3").Value.Value
newInputValue = deltaForcePercent*myInputParameter.Value.Value
print('New Force Load = ' + str(newInputValue))
ctr+=1
Parameters.SetBaseDesignPoint(DesignPoint=designPoint1)
Comments
-
While I can see the value in this implementation I want to offer some other parallel suggestions for similar use cases:
- You can do this same script concept in Mechanical alone without the need of parameters. You could simply solve>update force value in a loop until criteria is met. The benefit of this is less overhead of opening/closing Mechanical like the design points do on each iteration. The code would likely be even smaller as well. The problem is you don't have all the design points data unless you store them yourself.
- The other option is to use built in WB design optimization. This would be especially helpful if the output criteria and inputs are more complex. Optimization routines will try to get to the desired criteria as efficiently as possible by creating/reading 'response surfaces' and doing multi-dimensional interpolation to converge on desired values. This can be done with built in components without scripting.
0 -
@Mike.Thompson I agree.
The original customer query wanted to stay in Workbench and update geometry which likely means going back to Disco/Spaceclaim (and opening/updating). The example was designed to show how a WB output parameter (here from Mechanical) could be used to determine if a new DP was required.
And I, like the customer, see python as the hammer and all challenges as nails.
0 -
Perhaps this post would also be of interest in this case of modifying geometry.
0