How to parameterize the objective weight using Python Code object?

When performing Structural Optimization analysis in Mechanical, one can define multiple rows (corresponding to multiple analyses) in Objective, which will then activate the property "Weight" in the worksheet. One cannot parametrize these weights natively.
Best Answer
-
Starting from v2021R2, we can use Python Code object to parametrize non-parametrizable properties in Mechanical, such as Objective (for example) shown in the question.
This solution has been tested with v2023R1.
Here are the steps:
Step 1: After setting the Weights and analyses in the Objective worksheet, click on the analysis --> Write Input File (in the Environment Ribbon). After input file is written, suppress the Objective object in the Tree.
Step 2: Check the input file that was written and copy the lines indicating the Objective definition (so three lines as indicated below). Here, 24 and 69 correspond to Mechanical Object IDs of the 2 selected static structural analyses. These numbers might be different for your model. Please use the corresponding numbers in Python script in Step 5.
Step 3: RMB on Analysis --> Insert --> Commands. In the properties of Commands, set the "Target" as "Topology Optimization (Beta)" and paste the lines copied in Step 2 in here. So, this Commands object is an alternative way to define Objective worksheet.
Step 4: RMB on "Structural Optimization" in Mechanical --> Insert --> Python Code, and set the, "Target Callback" in the Properties to "After Object Changed"
Step 5: Python Code object has two tabs, "Script", "Property Provider". Script section is where we put our Mechanical script (python). Property Provider section is used to create custom properties (it can be float, text, drop down menu with options, geometry scoping etc)
- Property Provider:Replace the first function, def reload_props() in "Property Provider" tab of the Python Code window, with the below script and then, RMB on Python Code object --> Reload Properties. This should now show a custom output properties called "Weight Row 1" and "Weight Row 2"
def reload_props(): this.PropertyProvider = None # comment the following return to allow the rest of the function definition to be executed and add properties #return """ Some sample code is provided below that shows how to: 1. Create an instance of the Provider. The Provider class is used to add custom properties to the details. 2. Use the Provider instance to add custom properties. 3. Configure those custom properties. """ # Create the property instance provider = Provider() # Create a group named Group 1. group = provider.AddGroup("Weights") # Create a property with control type Expression and a property with control type Double, and add it to the Group 1 double_prop1 = group.AddProperty("Weight Row 1", Control.Double) double_prop2 = group.AddProperty("Weight Row 2", Control.Double) double_prop1.CanParameterize = True double_prop2.CanParameterize = True # Connects the provider instance back to the object by setting the PropertyProvider member on this, 'this' being the # current instance of the Python Code object. this.PropertyProvider = provider
- Script:Replace the entire script in the Script section of the Python code object with the below code
- This script takes in the Weights coming in from the custom properties defined in Python Code object and redefines the Commands in the Command object in Step 3, hence parametrizing the weights.
def after_object_changed(this, object_changed, property_name):# Do not edit this line """ Called after an object is changed. Keyword Arguments : this -- the datamodel object instance of the python code object you are currently editing in the tree object_changed -- The object that was changed property_name -- The property that was changed """ # To access properties created using the Property Provider, please use the following command. # this.GetCustomPropertyByPath("your_property_group_name/your_property_name") # To access scoping properties use the following to access geometry scoping and named selection respectively: # this.GetCustomPropertyByPath("your_property_group_name/your_property_name/Geometry Selection") # this.GetCustomPropertyByPath("your_property_group_name/your_property_name/Named Selection") #ObjectiveObj = ExtAPI.DataModel.GetObjectsByName("Objective_Parametric")[0] row1 = this.GetCustomPropertyByPath("Weights/Weight Row 1").Value row2 = this.GetCustomPropertyByPath("Weights/Weight Row 2").Value #ObjectiveObj.Worksheet.SetWeight(0,row1) #ObjectiveObj.Worksheet.SetWeight(1,row2) command_snippet = ExtAPI.DataModel.GetObjectsByName("Commands (TOPO) (Beta)")[0] command_snippet.Input = r"""! Commands inserted into this file will be executed just prior to the ANSYS SOLVE command. #Analysis Object IDs 24, 69 depends on analyses chosen. Please modify these numbers according to the input file written in Step 2 $Objective: objective1=COMP,Objective,24,all,no,{0} objective2=COMP,Objective,69,all,no,{1}""".format(row1,row2)
Step 6: RMB on Python Code object --> Connect
Step 7: Specify some numbers for the custom input properties to check if the Objective is getting updated based on the input numbers.
Step 8: and click on the check box to send this property as a parameter to WB (you can now see this under Parameter page in WB). One can now start the Design Point run to see the variation of output parameter for each Design Point.
3