How can I find elements that have a deformation value above a specified threshold and change their material properties for a subsequent analysis?
Here's an example.
First analysis
Insert a Python Code object in the Results and change the callback to After Post:
Code for Property provider:
def reload_props(): this.PropertyProvider = None # comment the following return to allow the rest of the function definition to be executed and add properties """ 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() group = provider.AddGroup("Inputs") double_prop = group.AddProperty("Threshold", Control.Double) this.PropertyProvider = provider
Code for script:
def after_post(this, solution):# Do not edit this line """ Called after post processing. Keyword Arguments : this -- the datamodel object instance of the python code object you are currently editing in the tree solution -- Solution """ # 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") import mech_dpf import Ans.DataProcessing as dpf import json import os mech_dpf.setExtAPI(ExtAPI) ds = dpf.DataSources(solution.Parent.ResultFileName) crit_disp = this.GetCustomPropertyByPath("Inputs/Threshold").Value model = dpf.Model(ds) mesh = model.Mesh all_elems = mesh.ElementIds disp = model.results.displacement() disp_norm = dpf.operators.math.norm_fc(disp) filt_disp = dpf.operators.filter.field_high_pass_fc(fields_container=disp_norm, threshold=crit_disp) nodes_crit = filt_disp.outputs.fields_container.GetData()[0].ScopingIds elements = [] mesh_con = mesh.NodalConnectivityPropertyField for node in nodes_crit: elements.append(mesh_con.GetEntityDataById(node)) elem_crit = list(set([all_elems[elem_index] for elem_list in elements for elem_index in elem_list])) elem_crit_scop = dpf.Scoping() elem_crit_scop.Ids = elem_crit # delete named selection if it already exists try: ns = ExtAPI.DataModel.GetObjectsByName('FILTERED_ELEMS')[0] ns.Delete() except: pass if len(elem_crit) != 0: # create named selection of filtered elements ns_filtered_elems = Model.AddNamedSelection() ns_filtered_elems.Name = "FILTERED_ELEMS" ns_filtered_elems.ScopingMethod = GeometryDefineByType.Worksheet criteria = ns_filtered_elems.GenerationCriteria for i in range(len(elem_crit)): criteria.Add(None) criteria[i].EntityType = SelectionType.MeshElement criteria[i].Criterion = SelectionCriterionType.ElementNumber criteria[i].Operator = SelectionOperatorType.Equal criteria[i].Value = elem_crit[i] ns_filtered_elems.Generate()
This will create a named selection of the elements that are above the specified threshold:
See also this post that explains the code behind filtering and shows a Python Result plot of them:
Second analysis
Insert a Python Code object in the analysis, with callback set to "Get solve commands".
Code for property provider:
def reload_props(): this.PropertyProvider = None # Create the property instance provider = Provider() group = provider.AddGroup("Inputs") # Create a property with control type Expression and a property with control type Double, and add it to the Group 1 scale_value = group.AddProperty("Coefficient factor for Young Modulus", Control.Double) # 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
scale_factor = this.GetCustomPropertyByPath("Inputs/Coefficient factor for Young Modulus").Value import materials first_body = Model.GetChildren(DataModelObjectCategory.Body, True)[0] material = ExtAPI.DataModel.GetObjectsByName(first_body.Material)[0] mat_enginerring_data = material.GetEngineeringDataMaterial() elasticity = materials.GetMaterialPropertyByName(mat_enginerring_data,"Elasticity") density = materials.GetMaterialPropertyByName(mat_enginerring_data,"Density") young_modulus = elasticity["Young's Modulus"][1] poisson_ratio = elasticity["Poisson's Ratio"][1] density = density["Density"][1] new_modulus = scale_factor*young_modulus solver_input_file.WriteLine("/PREP7") solver_input_file.WriteLine("MP,EX,999," + str(new_modulus) ) solver_input_file.WriteLine("MP,NUXY,999," + str(poisson_ratio) ) solver_input_file.WriteLine("MP,DENS,999," + str(density) ) solver_input_file.WriteLine("cmsel,s,FILTERED_ELEMS") solver_input_file.WriteLine("/PREP7") solver_input_file.WriteLine("emodif,all,mat,999") solver_input_file.WriteLine("ALLSELL") solver_input_file.WriteLine("/SOLU")
This code combines retrieving the material properties initially assigned to the first body in the tree, and using MAPDL commands to modify the Young Modulus assigned to the filtered elements.
Important note. Material properties retrieved through materials library are in MKS units. For robustness of the code, the solver unit system of the second analysis has to be in MKS:
Here's also the complete model.