Corner nodes scoping
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!
Comments
-
Maybe this post can help: https://discuss.ansys.com/discussion/2044/pydpf-remove-midside-nodes
0 -
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.0 -
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:
0 -
@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.
0 -
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
0 -
@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.
0 -
@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
0 -
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.
0 -
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!
1