How can I filter all nodes / elements above a certain result threshold using DPF / PyDPF?

Ayush Kumar
Ayush Kumar Member, Moderator, Employee Posts: 467
100 Answers 250 Likes 100 Comments Second Anniversary
✭✭✭✭

How can I filter all nodes / elements above a certain result threshold using DPF / PyDPF?

Tagged:

Comments

  • Ayush Kumar
    Ayush Kumar Member, Moderator, Employee Posts: 467
    100 Answers 250 Likes 100 Comments Second Anniversary
    ✭✭✭✭
    edited August 2023

    The following script filters all nodes above a value of 0.3mm total deformation and finds all the elements connected to those nodes.

    PyDPF

    from ansys.dpf import core as dpf
    
    rst_path = r"\Path\to\file.rst"
    ds = dpf.DataSources(rst_path)
    
    crit_disp = 0.3
    
    model = dpf.Model(ds)
    mesh = model.metadata.meshed_region
    
    mesh.plot()
    
    all_elems = mesh.elements.scoping.ids
    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.get_data()[0].scoping.ids
    
    elements = []
    mesh_con = mesh.property_field("reverse_connectivity")
    for node in nodes_crit:
        elements.append(mesh_con.get_entity_data_by_id(node))
    
    # Flatten the list #
    elem_crit_indexes = list(set([element for nested_elements in elements for element in nested_elements]))
    elem_crit_ids = [mesh.elements.scoping.ids[eid] for eid in elem_crit_indexes]
    
    elem_crit_scop = dpf.Scoping()
    elem_crit_scop.ids = elem_crit_ids
    
    crit_mesh = dpf.operators.mesh.from_scoping(mesh=mesh, scoping=elem_crit_scop).outputs.mesh.get_data()
    crit_mesh.plot()
    
    
    

    Mechanical DPF (IronPython)

    import mech_dpf
    import Ans.DataProcessing as dpf
    mech_dpf.setExtAPI(ExtAPI)
    
    analysis = Model.Analyses[0]
    ds = dpf.DataSources(analysis.ResultFileName)
    
    crit_disp = 0.3
    
    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
    
    

  • Pernelle Marone-Hitz
    Pernelle Marone-Hitz Member, Moderator, Employee Posts: 871
    100 Answers 500 Comments 250 Likes First Anniversary
    ✭✭✭✭
    edited August 2023

    To add to @Ayush Kumar 's solution, if you want to plot the filtered element numbers back to the model in Mechanical, this can be done in a Python Result Object.

    Edit Property Provider as follows:

    def reload_props():
    this.PropertyProvider = None
    # Create the property instance
    provider = Provider() group = provider.AddGroup("Inputs")

    double_prop = group.AddProperty("Threshold", 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

    Edit Script as follows:

    def define_dpf_workflow(analysis):
    import mech_dpf
    import Ans.DataProcessing as dpf
    mech_dpf.setExtAPI(ExtAPI) ds = dpf.DataSources(analysis.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

    # create new field and assign values
    my_field = dpf.FieldsFactory.CreateScalarField(numEntities=0, location='Elemental')
    my_field.MeshedRegionSupport = mesh
    for elem_id in elem_crit_scop.Ids:
    my_field.Add(elem_id,[float(elem_id)])
    my_field.ScopingIds = elem_crit_scop.Ids

    output = dpf.operators.utility.forward()
    output.inputs.any.Connect(my_field)

    dpf_workflow = dpf.Workflow()
    dpf_workflow.Add(output)
    dpf_workflow.SetOutputContour(output,dpf.enums.GFXContourType.FEElementalScoping)
    dpf_workflow.Record('wf_id', False)
    this.WorkflowId = dpf_workflow.GetRecordedId()

    Reload properties and evaluate result:

    This will plot the element number on the filtered elements: