In Mechanical scripting, how can I retrieve the data from a user-defined result and plot it as a Python Result ?
A user-defined result (UDR) is inserted in Mechanical :
A property is added to the Python Result for the user to provide the name of the UDR:
This is achieved by modifying the Property Provider of the Python Result:
The piece of code of interest here is:
def reload_props(): this.PropertyProvider = None # Create the property instance provider = Provider() input_group = provider.AddGroup("Input") ns_prop = input_group.AddProperty("UDR Name", Control.Expression) # 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
Then, the Script part of the Python Result is edited:
The code that is needed here is :
def post_started(sender, analysis):# Do not edit this line define_dpf_workflow(analysis) def define_dpf_workflow(analysis): # import DPF import mech_dpf import Ans.DataProcessing as dpf mech_dpf.setExtAPI(ExtAPI) # Connect to result file dataSource = dpf.DataSources(analysis.ResultFileName) # Retrieve mesh model=dpf.Model(dataSource) mesh=model.Mesh # whole mesh # Retrieve property values udr_name = str(this.GetCustomPropertyByPath("Input/UDR Name").Value) # Access User Defined Result and create a field out of it udr = ExtAPI.DataModel.GetObjectsByName(udr_name)[0] nb_nodes = len(udr.PlotData['Node']) # get number of nodes udr_field = dpf.FieldsFactory.CreateScalarField(nb_nodes) # instanciate field udr_field.MeshedRegionSupport = mesh # attach mesh udr_field.ScopingIds = udr.PlotData['Node'] # give list of nodes udr_field.Data = [0. for i in range(0,nb_nodes)]# fill field with zeros node_ids = udr.PlotData['Node'] values = [value for value in udr.PlotData['Values']] for ii in range(0,nb_nodes): index=udr_field.ScopingIds.IndexOf(node_ids[ii]) # get index of node in created field udr_field.UpdateEntityDataByEntityIndex(index,[values[ii]]) # Create field operator for plotting forward = dpf.operators.utility.forward_field() forward.inputs.field.Connect(udr_field) dpf_workflow = dpf.Workflow() dpf_workflow.Add(forward) dpf_workflow.SetOutputContour(forward) dpf_workflow.Record('wf_id', False) this.WorkflowId = dpf_workflow.GetRecordedId()
This code grabs the UDR, extract the values in it thanks to PlotData, and passes those values to a DPF Field to be able to plot it in the Python Result object.
Pernelle: Thanks so much for posting this! I was able to do some (work) cool application by mouse click applying it but it failed with automation Why? DPF Python Result is "def post_started(sender, analysis):", i.e. it runs before UDR data is populated by post. On the other hand, a Python Code object is "def after_post(this, solution)", i.e. it runs after UDR data is populated by post - what is needed to use UDR results in DPF with automation. Do you have any suggestions for how to do this? I tried putting time.sleep(time_sleep) in the DPF code but it did not work. Cordially, Ray
Hi @Ray_Greene , glad you found that post useful! Indeed I hadn't realized this would not work in an automated way. There is unfortunately no workaround possible, the only solution would be to execute the two objects manually and in a successive manner. I also tried having a Python Code object in "after post" unsuppress the Python Result and evaluate, but Python Results do not have a Suppressed / Unsuppressed status so this is not a viable path either. Looks like something that could be improved, I'll let the developers know.
Hi @Pernelle Marone-Hitz, you saved my day with this post ! I was wondering if there is a way to enlarge an existing field as well ? Say that we loop over multiple results instead of taking into account only one and we would enlarge the field as we loop over the different results. I did not find a way to do it in a unique loop so I made a first loop to know the list of nodes to initialize the field to the full size and loop then again to fill the values. Probably not the most efficient but since I am working on a small field it's ok for now. Thanks,
Josselin
Hi Josselin ! Glad that you found this useful. I guess what you're looking for is something like .append() for a Python list. I'm not aware that this exists for DPF but maybe @Ayush Kumar and/or @Paul Profizi would know better.
Hi @Pernelle Marone-Hitz, hi @Josselin GUEDON, I think you might find the utility incremental operators useful. You should be able to connect the first input multiple times and the operator will perform a merging operation when the output is requested.