How to access tabular data values in Mechanical scripting without the GUI open?
I want to access the tabular data values of Mechanical result objects, but I need to do that without the GUI open, so the GetPane() approach will not work. Also, the mechanical objects are reaction probes, so they do not have ExportToTextFile method.
I understand that we can create a result object for each output time step and read the value at the displayed time instead of from the table, but I am hoping to see if there are any alternatives that are more efficient and elegant.
Answers
-
The most stable way to do this is bypass the objects and recreate the post processing with DPF. In general you can use the element nodal forces operator to get reaction probe data. If you have more specifics then please post, but in general it would be great to have a DPF based method that recreates the probe calcs.
1 -
The tabular data is calculated on the fly by the GUI, so there is no way to get it directly in batch mode.
Here is a hack I put together a while ago. Hope it is useful. Full file is attached in case I missed any needed functions.APINames = ['Minimum','Maximum','Average'] def GetTabularData(obj): ExtAPI.Log.WriteMessage('GetTabularData..') TableProps = GetTableProperties(obj) return TP2TD(obj,TableProps) def GetTableProperties(obj): ExtAPI.Log.WriteMessage('GetTableProperties...') VisProps = obj.VisibleProperties TableProps = [] if not IsResult(obj): for p in VisProps: if p.APIName != None: prop = getattr(obj,p.APIName) if prop.GetType() == Ansys.ACT.Mechanical.Fields.Field: TableProps.Add(prop) # with open(r'D:\test.txt','w') as f: # f.write(prop.Output.Name) #prop.Inputs[0].Name else: TableProps = [getattr(obj,APIName) for APIName in APINames] return TableProps def TP2TD(obj,tp): ExtAPI.Log.WriteMessage('TP2TD...') ExtAPI.Log.WriteMessage('debug0') # Would be more efficient to update all objs at once if not IsResult(obj): ExtAPI.Log.WriteMessage('Load') td0 = [] td0.Add('Time [s]') for p in tp: ExtAPI.Log.WriteMessage('debug1: {}'.format(p.Name)) td0.Add(p.Output.Name+' [{}]'.format(p.Output.Unit)) if p.Output.DiscreteValueCount == 0 and p.Output.DefinitionType == p.Output.DefinitionType.Formula: ExtAPI.Log.WriteMessage('DiscreteValueCount == 0') formula = p.Output.Formula p.Output.Formula = formula td = [td0] if len(tp)>0: for i in range(p.Output.DiscreteValueCount): row = [str(tp[0].Inputs[0].DiscreteValues[i].Value)] for p in tp: row.Add(str(p.Output.DiscreteValues[i].Value)) td.Add(row) else: ExtAPI.Log.WriteMessage('Result') units = [str(getattr(obj,APIName).Unit) for APIName in APINames] td0 = [] td0.Add('Time [s]') ExtAPI.Log.WriteMessage('debug2') for APIName,unit in zip(APINames,units): td0.Add('{} [{}]'.format(APIName,unit)) td = [td0] analysis = obj.Parent.Parent #SOK? if os.path.isfile(analysis.ResultFileName): # Just neeed row0 for output list with analysis.GetResultsData() as reader: Timepoints = reader.ListTimeFreq obj.By = obj.By.ResultSet obj.CalculateTimeHistory = False ExtAPI.Log.WriteMessage('debug3') for i,time in enumerate(Timepoints): obj.SetNumber = i+1 obj.EvaluateAllResults() values = [str(time)]+[str(getattr(obj,APIName).Value) for APIName in APINames] td.Add(values) return td def IsResult(obj): #Is there a Better way? return 'Ansys.ACT.Automation.Mechanical.Results' in str(obj.GetType())
0 -
@Mike.Thompson said:
The most stable way to do this is bypass the objects and recreate the post processing with DPF. In general you can use the element nodal forces operator to get reaction probe data. If you have more specifics then please post, but in general it would be great to have a DPF based method that recreates the probe calcs.Hi Mike, thanks for your suggestion! I am looking into a DPF solution now.
0 -
@Landon Mitchell Kanner said:
The tabular data is calculated on the fly by the GUI, so there is no way to get it directly in batch mode.
Here is a hack I put together a while ago. Hope it is useful. Full file is attached in case I missed any needed functions.APINames = ['Minimum','Maximum','Average'] def GetTabularData(obj): ExtAPI.Log.WriteMessage('GetTabularData..') TableProps = GetTableProperties(obj) return TP2TD(obj,TableProps) def GetTableProperties(obj): ExtAPI.Log.WriteMessage('GetTableProperties...') VisProps = obj.VisibleProperties TableProps = [] if not IsResult(obj): for p in VisProps: if p.APIName != None: prop = getattr(obj,p.APIName) if prop.GetType() == Ansys.ACT.Mechanical.Fields.Field: TableProps.Add(prop) # with open(r'D:\test.txt','w') as f: # f.write(prop.Output.Name) #prop.Inputs[0].Name else: TableProps = [getattr(obj,APIName) for APIName in APINames] return TableProps def TP2TD(obj,tp): ExtAPI.Log.WriteMessage('TP2TD...') ExtAPI.Log.WriteMessage('debug0') # Would be more efficient to update all objs at once if not IsResult(obj): ExtAPI.Log.WriteMessage('Load') td0 = [] td0.Add('Time [s]') for p in tp: ExtAPI.Log.WriteMessage('debug1: {}'.format(p.Name)) td0.Add(p.Output.Name+' [{}]'.format(p.Output.Unit)) if p.Output.DiscreteValueCount == 0 and p.Output.DefinitionType == p.Output.DefinitionType.Formula: ExtAPI.Log.WriteMessage('DiscreteValueCount == 0') formula = p.Output.Formula p.Output.Formula = formula td = [td0] if len(tp)>0: for i in range(p.Output.DiscreteValueCount): row = [str(tp[0].Inputs[0].DiscreteValues[i].Value)] for p in tp: row.Add(str(p.Output.DiscreteValues[i].Value)) td.Add(row) else: ExtAPI.Log.WriteMessage('Result') units = [str(getattr(obj,APIName).Unit) for APIName in APINames] td0 = [] td0.Add('Time [s]') ExtAPI.Log.WriteMessage('debug2') for APIName,unit in zip(APINames,units): td0.Add('{} [{}]'.format(APIName,unit)) td = [td0] analysis = obj.Parent.Parent #SOK? if os.path.isfile(analysis.ResultFileName): # Just neeed row0 for output list with analysis.GetResultsData() as reader: Timepoints = reader.ListTimeFreq obj.By = obj.By.ResultSet obj.CalculateTimeHistory = False ExtAPI.Log.WriteMessage('debug3') for i,time in enumerate(Timepoints): obj.SetNumber = i+1 obj.EvaluateAllResults() values = [str(time)]+[str(getattr(obj,APIName).Value) for APIName in APINames] td.Add(values) return td def IsResult(obj): #Is there a Better way? return 'Ansys.ACT.Automation.Mechanical.Results' in str(obj.GetType())
Hi Landon, thank you so much for your response! I tested your code on my model, it seems like it relies on the Maximum/Mininum/Average attributes of the result object. This works well for getting the max of the temperature fields, but these attributes are not available for a thermal reaction probe, so I was unable to use this to get reaction force values.
0 -
To refine my question a bit more given the added information from the previous responses, I am now looking to extract results using DPF. I have a thermal analysis and I am looking to extract the total heat rate (in Watts) over a named selection. This can be done in Mechanical by a reaction probe scoped to the named selection. So, I started with the reaction_force and nodal_force operators in DPF. However, neither of those seem to be available for a rth file.
I have the following workaround using heat flux:
op = dpf.operators.result.heat_flux() # operator instantiation op.inputs.data_sources.Connect(data_sources) # op.inputs.requested_location.Connect('Nodal') op.inputs.mesh_scoping.Connect(mesh_scoping) op.inputs.time_scoping.Connect(time_scoping) norm = dpf.operators.math.norm_fc() # operator instantiation norm.inputs.fields_container.Connect(op) sum_op = dpf.operators.math.accumulate_fc() # operator instantiation sum_op.inputs.fields_container.Connect(norm) my_scale_factor = 1e-6 / len(node_ids) * face_area scale = dpf.operators.math.scale_fc() # operator instantiation scale.inputs.fields_container.Connect(sum_op) scale.inputs.ponderation.Connect(my_scale_factor) heat_rate = scale.outputs.fields_container.GetData()
but this sometimes give some large errors, presumably because dpf.operators.result.heat_flux() by default returns results in element_nodal location, when passed a nodal named selection (switching output location to nodal), some operations are performed under the hood (https://github.com/ansys/pydpf-core/issues/258), but I am not 100% sure.
Could anyone suggest a better method to get the total heat rate on the named selection? Thanks a lot!
0