Filter elements with deformation above a value and change their material properties
How can I find elements that have a deformation value above a specified threshold and change their material properties for a subsequent analysis?
Comments
-
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 = providerCode 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 = providerCode for script:
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.
1