Corner nodes scoping

MareTom
MareTom Member Posts: 5
First Comment First Anniversary Name Dropper
**

Hello team!
I need support to do the right scoping on the corner nodes in my script.
I'm using the following code:

prop_operator_global = dpf.operators.result.structural_temperature()
prop_operator_global.inputs.streams_container.connect(stream)
prop_operator_global.inputs.time_scoping.connect(tf_list)
prop_operator_global.inputs.requested_location('Nodal')
prop_container = prop_operator_global.outputs.fields_container()
del prop_operator_global

for s in range (0, len(components)):
    comp_element_s = components[s]

    my_int_inclusive = 0
    op_scoping = dpf.operators.scoping.on_named_selection() # operator instantiation
    op_scoping.inputs.requested_location.connect('Nodal')
    op_scoping.inputs.named_selection_name.connect(comp_element_s)
    op_scoping.inputs.int_inclusive.connect(my_int_inclusive)# optional
    op_scoping.inputs.streams_container.connect(stream)# optional
    op_scoping.inputs.data_sources.connect(r)
    my_mesh_scoping = op_scoping.outputs.mesh_scoping()

    # ONLY CORNER
    from_scoping_to_mesh = dpf.operators.mesh.from_scoping() # operator instantiation
    from_scoping_to_mesh.inputs.scoping.connect(my_mesh_scoping)
    from_scoping_to_mesh.inputs.inclusive.connect(0)
    from_scoping_to_mesh.inputs.mesh.connect(r.metadata.meshed_region)
    my_mesh = from_scoping_to_mesh.outputs.mesh()

    op_corner = dpf.operators.scoping.connectivity_ids(mesh_scoping=my_mesh.elements.scoping,mesh=my_mesh, take_mid_nodes=False)
    corner_node_ids = list(set(op_corner.outputs.mesh_scoping().ids))
    my_mesh_scoping = dpf.Scoping(location=dpf.locations.nodal)
    my_mesh_scoping.ids = corner_node_ids

    my_default_value = float()
    op = dpf.operators.scoping.rescope_fc() # operator instanciation
    op.inputs.fields_container.connect(prop_container)
    op.inputs.mesh_scoping.connect(my_mesh_scoping)
    op.inputs.default_value.connect(my_default_value)
    prop_container_comp = op.outputs.fields_container()

    list_nodes = prop_container_comp[0].scoping.ids

    print (comp_element_s + "-Nodes number: "+ str(len(list_nodes)))

But, I obtained for some components 0 nodes in the scoping (in particular if the named selection is already without the mid side nodes).

Thanks!

Tagged:

Comments

  • Pernelle Marone-Hitz
    Pernelle Marone-Hitz Member, Moderator, Employee Posts: 871
    500 Comments Photogenic Name Dropper Solution Developer Community of Practice Member
    ✭✭✭✭
  • MareTom
    MareTom Member Posts: 5
    First Comment First Anniversary Name Dropper
    **

    Hello Pernelle!
    No it is not useful. I started that conversation some time ago, and it was only on how get the corner nodes.
    Now I'm getting the corner nodes (thru a some line of code taken from the link you suggested), but if I try the scoping on a named selection that already in Ansys mechanical has only the corner nodes I obtain a scoping with 0 node, while I expect to obtain the same number of nodes of the original named selection.

  • Pernelle Marone-Hitz
    Pernelle Marone-Hitz Member, Moderator, Employee Posts: 871
    500 Comments Photogenic Name Dropper Solution Developer Community of Practice Member
    ✭✭✭✭

    Hi @MareTom ,
    Not sure I fully understand your issue here, but I don't seem to be able to reproduce it. BTW I'm using 2024R2. I have the following NSs in Mechanical:

    SINGLE_ELEM is a hexa quad elem (20 nodes) and CORNER_NODES is filtering only the corner nodes (8 nodes).
    Using the following script:

    import mech_dpf
    import Ans.DataProcessing as dpf
    mech_dpf.setExtAPI(ExtAPI)
    #Get path to result file
    analysis = ExtAPI.DataModel.Project.Model.Analyses[0]
    filepath = analysis.ResultFileName
    #Data sources
    dataSources = dpf.DataSources()
    dataSources.SetResultFilePath(filepath)
    #Scoping on named selection
    scoping_on_ns_1 = dpf.operators.scoping.on_named_selection()
    scoping_on_ns_1.inputs.requested_location.Connect('Nodal')
    scoping_on_ns_1.inputs.named_selection_name.Connect('SINGLE_ELEM')
    scoping_on_ns_1.inputs.data_sources.Connect(dataSources)
    my_mesh_scoping__1 = scoping_on_ns_1.outputs.mesh_scoping.GetData()
    #Scoping on named selection
    scoping_on_ns_2 = dpf.operators.scoping.on_named_selection()
    scoping_on_ns_2.inputs.requested_location.Connect('Nodal')
    scoping_on_ns_2.inputs.named_selection_name.Connect('CORNER_NODES')
    scoping_on_ns_2.inputs.data_sources.Connect(dataSources)
    my_mesh_scoping__2 = scoping_on_ns_2.outputs.mesh_scoping.GetData()
    

    I obtain the following:

  • Ayush Kumar
    Ayush Kumar Member, Moderator, Employee Posts: 449
    250 Likes Solution Developer Community of Practice Member Ansys Employee First Anniversary
    ✭✭✭✭

    @MareTom, please check if the named selection you created in Mechanical has also landed in the RST. You can check for components under Worksheet in Mechanical to see component names in the result file. In general a resolve after you have defined a named selection in Mechanical should suffice.

  • MareTom
    MareTom Member Posts: 5
    First Comment First Anniversary Name Dropper
    **

    Hi team!
    @Ayush Kumar , yes I can see all in the RST all the named selection:

    @Pernelle Marone-Hitz I'm using 2023R2, but the behavior is the same also in 2024R1 (but I'm quite sure I'm doing something wrong).
    In the example posted you are only printing the named selections and it is working also in my case:

    Where "CIL_N" is a whole component and "CIL_N_CORNER" is the same component with the filter on the corner nodes.
    If I try to get the number of the nodes for each components I get the right number:

    But if I try from a script to remove the mid side nodes (on both the named selection, with the script I posted at the beginning), the first one (the one with all the nodes) is good, the second one (the one where I already removed the mid side nodes from the named selection) gets 0 node:

    While I was expecting to get the same number of nodes for both the named selections.

    I can manage it from the inputs, performing a check at the beginning of the script to "validate" the input and exclude all the case I know they'll fail, but I would like to make the script more robust and generic for all the cases.

    Thanks

  • Ayush Kumar
    Ayush Kumar Member, Moderator, Employee Posts: 449
    250 Likes Solution Developer Community of Practice Member Ansys Employee First Anniversary
    ✭✭✭✭

    @MareTom seems to work fine for me with 241. Can you please check if you get the same issue within Mechanical? Basically, with DPF scripting in Mechanical. If yes, please log a support ticket and share your RST.

  • MareTom
    MareTom Member Posts: 5
    First Comment First Anniversary Name Dropper
    **

    @Ayush Kumar try to use the following code:

    prop_operator_global = dpf.operators.result.structural_temperature()
    prop_operator_global.inputs.streams_container.connect(stream)
    prop_operator_global.inputs.time_scoping.connect(tf_list)
    prop_operator_global.inputs.requested_location('Nodal')
    prop_container = prop_operator_global.outputs.fields_container()
    del prop_operator_global
    
    for s in range (0, len(components)):
        comp_element_s = components[s]
    
        my_int_inclusive = 0
        op_scoping = dpf.operators.scoping.on_named_selection() # operator instantiation
        op_scoping.inputs.requested_location.connect('Nodal')
        op_scoping.inputs.named_selection_name.connect(comp_element_s)
        op_scoping.inputs.int_inclusive.connect(my_int_inclusive)# optional
        op_scoping.inputs.streams_container.connect(stream)# optional
        op_scoping.inputs.data_sources.connect(r)
        my_mesh_scoping = op_scoping.outputs.mesh_scoping()
    
        # ONLY CORNER
        from_scoping_to_mesh = dpf.operators.mesh.from_scoping() # operator instantiation
        from_scoping_to_mesh.inputs.scoping.connect(my_mesh_scoping)
        from_scoping_to_mesh.inputs.inclusive.connect(0)
        from_scoping_to_mesh.inputs.mesh.connect(r.metadata.meshed_region)
        my_mesh = from_scoping_to_mesh.outputs.mesh()
    
        op_corner = dpf.operators.scoping.connectivity_ids(mesh_scoping=my_mesh.elements.scoping,mesh=my_mesh, take_mid_nodes=False)
        corner_node_ids = list(set(op_corner.outputs.mesh_scoping().ids))
        my_mesh_scoping = dpf.Scoping(location=dpf.locations.nodal)
        my_mesh_scoping.ids = corner_node_ids
    
        my_default_value = float()
        op = dpf.operators.scoping.rescope_fc() # operator instanciation
        op.inputs.fields_container.connect(prop_container)
        op.inputs.mesh_scoping.connect(my_mesh_scoping)
        op.inputs.default_value.connect(my_default_value)
        prop_container_comp = op.outputs.fields_container()
    
        list_nodes = prop_container_comp[0].scoping.ids
        print (comp_element_s + "-Nodes number: "+ str(len(list_nodes)))
    

    Because in your example there isn't the scoping on the corner nodes

  • Pernelle Marone-Hitz
    Pernelle Marone-Hitz Member, Moderator, Employee Posts: 871
    500 Comments Photogenic Name Dropper Solution Developer Community of Practice Member
    ✭✭✭✭
    edited September 24

    Hi @MareTom , thanks for clarifying, I now understand what is the issue you're having. Note, there is an enhancement request open to make selecting corner nodes and midside nodes more easily, I'd encourage you to write a comment in there to push for it: https://github.com/ansys/pydpf-core/issues/780

    Coming back to your issue, I worked in Mechanical for simplicity but the problem is the same. I modified the model slightly (still working on a single element as it helps understand the behavior):

    The code that I had shared previously becomes:

    import mech_dpf
    import Ans.DataProcessing as dpf
    mech_dpf.setExtAPI(ExtAPI)
    #Get path to result file
    analysis = ExtAPI.DataModel.Project.Model.Analyses[0]
    filepath = analysis.ResultFileName
    #Data sources, model and mesh
    dataSources = dpf.DataSources()
    dataSources.SetResultFilePath(filepath)
    model = dpf.Model(dataSources)
    whole_mesh = model.Mesh
    #Scoping on named selection #1
    scoping_on_ns_all_nodes = dpf.operators.scoping.on_named_selection()
    scoping_on_ns_all_nodes.inputs.requested_location.Connect('Nodal')
    scoping_on_ns_all_nodes.inputs.named_selection_name.Connect('ALL_NODES_ON_ELEM')
    scoping_on_ns_all_nodes.inputs.data_sources.Connect(dataSources)
    my_mesh_scoping_all_nodes = scoping_on_ns_all_nodes.outputs.mesh_scoping.GetData()
    #Scoping on named selection #2 
    scoping_on_ns_corner = dpf.operators.scoping.on_named_selection()
    scoping_on_ns_corner.inputs.requested_location.Connect('Nodal')
    scoping_on_ns_corner.inputs.named_selection_name.Connect('CORNER_NODES')
    scoping_on_ns_corner.inputs.data_sources.Connect(dataSources)
    my_mesh_scoping_corner = scoping_on_ns_corner.outputs.mesh_scoping.GetData()
    print('Scoping on "all nodes on elem" NS gives: ' + '\n' + str(my_mesh_scoping_all_nodes))
    print('Scoping on "corner nodes" NS gives: ' + '\n' + str(my_mesh_scoping_corner))
    

    and returns, as expected:

    The problem lies just after, with the "mesh from scoping" operator. Code I used for testing the influence of "inclusive" and "nodes only" pins:

    # Mesh from scopings
    mesh_from_scoping_all_nodes = dpf.operators.mesh.from_scoping() 
    mesh_from_scoping_all_nodes.inputs.scoping.Connect(my_mesh_scoping_all_nodes)
    mesh_from_scoping_all_nodes.inputs.inclusive.Connect(0)
    #mesh_from_scoping_all_nodes.inputs.nodes_only.Connect(True)
    mesh_from_scoping_all_nodes.inputs.mesh.Connect(whole_mesh)
    my_mesh_all_nodes = mesh_from_scoping_all_nodes.outputs.getmesh()
    mesh_from_scoping_corner_nodes = dpf.operators.mesh.from_scoping() 
    mesh_from_scoping_corner_nodes.inputs.scoping.Connect(my_mesh_scoping_corner)
    mesh_from_scoping_corner_nodes.inputs.inclusive.Connect(0)
    #mesh_from_scoping_corner_nodes.inputs.nodes_only.Connect(True)
    mesh_from_scoping_corner_nodes.inputs.mesh.Connect(whole_mesh)
    my_mesh_corner_nodes = mesh_from_scoping_corner_nodes.outputs.getmesh()
    print('Mesh on "all nodes on elem" NS gives: ' + '\n' + str(my_mesh_all_nodes))
    print('Mesh on "corner nodes" NS gives: ' + '\n' + str(my_mesh_corner_nodes))
    

    This works fine for the case where we have all the nodes (corner and midside) in the NS, we end up with the entire element and its 20 nodes. However this can't work with the NS where we only have midside nodes:

    • if we're using "inclusive"==1, we're getting all surrounding elements

    • if we're using "nodes_only"== False (default), we're asking to grab the elements with all their nodes in the scoping, hence for the NS with only corner nodes, we grab nothing:

    • if we're using "nodes_only"== True then we get the correct number of nodes, but no element (which makes sense as we're specifically asking that we don't grab the elements)

    My conclusion from this investigation is that there is nothing wrong in your code, nor in DPF behavior. The correct workflow would be to not filter the nodes in Mechanical and filter them in DPF, and it would work correctly.

  • MareTom
    MareTom Member Posts: 5
    First Comment First Anniversary Name Dropper
    **

    Hi @Pernelle Marone-Hitz ,

    Thanks a lot for your check!
    I hoped to find a more robust scoping to cover also this situation.
    Anyway I'll write very details users practice to avoid any error.

    Thanks!