Python Result example - mapping data
Is there an example of Python Result to map result data from one mesh to another mesh?
Answers
-
Here's an example. This examples grabs the equivalent stress of another analysis, maps it to the current mesh, and plots the difference between the current equivalent stress and the equivalent stress obtained in the other analysis.
Insert a Python Result object:
Modify the define_dpf_workflow() method by copying and pasting the code below. Make sure to modify the path to the other result file! Also, due to formatting issues, please note that everything after the first line has to be indented - in doubt, download the model attached in another post, it contains the code with correct formatting.
def define_dpf_workflow(analysis): import os
import mech_dpf
import Ans.DataProcessing as dpf
mech_dpf.setExtAPI(ExtAPI)
path_to_other_rst = os.path.join('C:\Users\Test','file.rst') # MODIFY THIS TO YOUR PATH
analysis = ExtAPI.DataModel.Project.Model.Analyses[0]
dataSource_1 = dpf.DataSources(analysis.ResultFileName)
dataSource_2 = dpf.DataSources(path_to_other_rst)
model_1 = dpf.Model(dataSource_1)
mesh_1 = model_1.Mesh
model_2 = dpf.Model(dataSource_2)
mesh_2 = model_2.Mesh
seqv_1 = dpf.operators.result.stress_von_mises()
seqv_1.inputs.data_sources.Connect(dataSource_1)
seqv_2 = dpf.operators.result.stress_von_mises()
seqv_2.inputs.data_sources.Connect(dataSource_2)
mapping_op = dpf.operators.mapping.on_coordinates()
mapping_op.inputs.coordinates.Connect(mesh_1.CoordinatesField)
mapping_op.inputs.fields_container.Connect(seqv_2.outputs.fields_container)
mapping_op.inputs.mesh.Connect(mesh_1)
minus_fc = dpf.operators.math.minus_fc()
minus_fc.inputs.field_or_fields_container_A.Connect(seqv_1.outputs.fields_container)
minus_fc.inputs.field_or_fields_container_B.Connect(mapping_op.outputs.fields_container.GetData())
output = dpf.operators.utility.forward()
output.inputs.any.Connect(minus_fc)
dpf_workflow = dpf.Workflow()
dpf_workflow.Add(output)
dpf_workflow.SetOutputContour(output)
dpf_workflow.Record('wf_id', False)
this.WorkflowId = dpf_workflow.GetRecordedId()You can then connect and evaluate the result:
0 -
@Pernelle Marone-Hitz , can you please also post the .wbpz file for the full context?
0 -
@Mike.Thompson This is just a dummy model. Solve C component, store .rst somewhere, modify Python Result in B to grab the path to .rst from C. Models don't even have to be in the same Workbench project.
1 -
Important note: to get better handling of midside nodes, starting from 2024R1 use the newly added pin "use_quadratic_elements":
mapping_op.inputs.use_quadratic_elements.Connect(True)
This is specifically useful for distorted quadratic elements.0 -
If, instead of comparing two meshes, we want to map our results to a mesh done by a third-party tool, we can make use of the same operator, but we generate a field which contains the nodes coordinates from that third-party tool. Below the script which reads the nodes coordinates from fcoordinates_file (I took coarse mesh nodal coordinates of Pernelle's example) and maps the displacement solution:
import os import mech_dpf import Ans.DataProcessing as dpf analysis=Model.Analyses[0] dataSource = dpf.DataSources(analysis.ResultFileName) model=dpf.Model(dataSource) rst_mesh=model.Mesh op_d = dpf.operators.result.displacement() op_d.inputs.data_sources.Connect(dataSource) d_fc = op_d.outputs.fields_container.GetData() path = 'here_your_path' coordinates_file = os.path.join(path,'CoordinatesFiles.txt') with open(coordinates_file, 'r') as f: data = f.readlines() coordinates = [] [coordinates.append(line.strip().split()) for line in data] coordinates = [[float(item) for item in inner_list] for inner_list in coordinates] fields_coordinates = dpf.FieldsFactory.Create3DVectorField(numEntities=len(coordinates),location='Nodal') [fields_coordinates.Add(i,coordinates[i-1]) for i in range(1,len(coordinates)+1)] op = dpf.operators.mapping.on_coordinates() op.inputs.fields_container.Connect(d_fc) op.inputs.coordinates.Connect(fields_coordinates) op.inputs.create_support.Connect(True) op.inputs.mesh.Connect(rst_mesh) my_fields_container = op.outputs.fields_container.GetData()
Please be aware that newly added pin mapping_op.inputs.use_quadratic_elements.Connect(True) is not available in Ansys 2023R2, that's why it is not used, but it is recommended.
1 -
Hello everyone,
I was working with the example TestModel_Mapped.wbpz from @Pernelle Marone-Hitz (Uploaded August 9th) and on my side I have problems recreating the correct results.
I use Ansys 2023 R2.02.
When using the exact settings and Model (finer mesh in Model 2 and coarse mesh in model 1), I get way different mapped results:
When using the same mesh (6 mm) for model 2 and 1 I get good results:
There seems to be a mesh dependency (which in some way is o.k. but this seems to be a bigger problem).
Without using:
mapping_op.inputs.mesh.Connect(mesh_1)
the results are way better. From the documentation:
https://dpf.docs.pyansys.com/version/stable/api/ansys.dpf.core.operators.mapping.on_coordinates.html
this command is just optional, but should still work, right?Anyone observed similar problems or know where this comes from?
Thank you very much!
Best regards
Ludwig0 -
short update:
I tested the exact same project in 2024R1 and the problem still appears.Can anyone confirm this problem?
Thanks!
Ludwig0 -
Hello @LudwigK,
I think I experienced the same issue, removing the line mapping_op.inputs.mesh.Connect(mesh_1) seems to show better results.
This plot is only the mapping of the refine mesh results (C) onto the coarse mesh (B).
When I keep connecting mesh_1, I get this :
However I am not sure how to get a better contour plot.
@Pernelle Marone-Hitz , @Mike.Thompson would you have a clue ?Thanks.
Josselin0 -
@Josselin GUEDON , can you please try with 2024R1 ? If the problem can be reproduced with the latest version, please open an official support case and I will look further into it.
0 -
@Pernelle Marone-Hitz , I believe I can reproduce the problem in the latest version and it gives me somewhat an even worst plot (with holes in it) :
I have opened a SR as you requested.
For information, this test case is not customer related.Josselin
0 -
Thanks @Josselin GUEDON , we'll look into this. Looks like something's off and could well be a bug.
0 -
You should also be aware of many mapping additions at V24.1. You can now use the mapping that mechanical/workbench has used for many releases in DPF.
0 -
Hi all, I had some feedback from the DPF team and there are two things to mention here:
- Issue when using
mapping_op.inputs.mesh.Connect(mesh_1)
: This is an error on my side, this line should not have been used here. Additional information for everyone to have a better understanding:
The mapping_on_coordinates operator works by mapping an input field/fields_container (input 0) on a set of nodes (input 1). Then, there are the following configuration (optional) inputs:
- create_support (input 2): this creates a MeshedSupport for the output FieldsContainer, consisting on a "fake" MeshedRegion with as many nodes as nodes there are in the set of input nodes (input 1), with point elements.
- mapping_on_scoping (input 3): this just restricts the mapping to the scoping of the first Field of the FieldsContainer. This is to enhance performance (for example, if your FC has 2000 fields, one for each time step, and the mesh doesn't change, you can compute interpolation weights for just one Scoping and then apply it to all of them).
- use_quadratic_elements (input 200): this enhances the way elements are searched. At the end of the day, we are mapping based on shape functions in a mesh, so the first step is to locate each node in input 1 in the mesh. If the element is quadratic, the sides can be parabolas, and taking this detail into account may lead to a more correct element identification. It, however, means spending more time in this search/locate step. Therefore, the default is False (as a general rule, quadratic elements are not normally that distorted). This was added in 24R1.
- mesh (input 7): this is the key. If this pin is not connected, the mesh used to locate the input nodes will be the support of the input field. However, if connected, this will be the input mesh.
In the case here, we are mapping the results of a fine mesh into a coarse mesh. However, the operator was connected like this:
mapping_op = dpf.operators.mapping.on_coordinates() mapping_op.inputs.coordinates.Connect(nodes_of_coarse_mesh) mapping_op.inputs.fields_container.Connect(nodal_result_on_fine_mesh) mapping_op.inputs.use_quadratic_elements.Connect(True) mapping_op.inputs.mesh.Connect(coarse_mesh)
The connections above don't make sense. We were using as "mesh" in input 7 a mesh that has nothing to do with the support of of nodal_result_on_fine_mesh: What is node 245 (for example) in the scoping of nodal_result_on_fine_mesh has nothing to do with the meaning of node 245 in coarse_mesh. Hence the first plot with random values.
- Plot with holes: Mapping results onto an external mesh is a very tricky operation involving many tolerances and estimations. A coarse mesh will most likely result in some missed mappings because it is impossible to find a "best" tolerance that works for all meshes. Whenever we 'miss' a node, the mapping will fail and that will result in an incomplete/patchy display. (Mechanical's policy is that it will draw/color-in the full element only if all nodes belonging to that element have result values. Else, it will only draw/color the nodes but the 'interior' of the element will not be filled in)
0 - Issue when using
-
Hi, all.
@Pernelle Marone-Hitz @Josselin GUEDON @Javier Vique
Thanks for the great topic in the post. I have successfully replicated all the test results in Pernelle's example. However, I encountered a problem when I wanted to map the displacement results. If I keep everything else the same and only change the target results fromseqv_1 = dpf.operators.result.stress_von_mises() seqv_1.inputs.data_sources.Connect(dataSource_1) seqv_2 = dpf.operators.result.stress_von_mises() seqv_2.inputs.data_sources.Connect(dataSource_2)
to
seqv_1 = dpf.operators.result.displacement() seqv_1.inputs.data_sources.Connect(dataSource_1) seqv_2 = dpf.operators.result.displacement() seqv_2.inputs.data_sources.Connect(dataSource_2)
Then, mapped data will only yield null results. I have also tested 'displacement_X', 'displacement_Y', and 'displacement_Z'; none of them can produce any results.
However, all strain and stress results can be mapped properly. I am wondering if there may be something wrong with mapping the displacement results. I have also had the same issue reported in my post. The link is given below:
https://discuss.ansys.com/discussion/4613/read-results-at-the-specific-locations#latest
0