How to assess the maximum stress range for a fatigue assessment when there are several load cases?

Member, Employee Posts: 3
First Anniversary Ansys Employee First Comment Photogenic
✭✭✭
edited June 2023 in Structures

This might be a trivial task if there is a manageable number of load cases. Once the load case number is increasing and/or the data is sitting in different result files the effort for doing it may get time consuming.

Tagged:

Answers

  • Member, Employee Posts: 3
    First Anniversary Ansys Employee First Comment Photogenic
    ✭✭✭
    edited May 2023

    One way would be via a python result object in conjunction with the Data Processing Framework module, to fetch the according data and evaluate the maximum stress range over all time points. Further on, it is possible to reference other result files to include these within the evaluation, assuming they are utilizing the same mesh (Node IDs). This example will perform the stress range based on maximum and minimum principal stress.

    To enable this, you will need to include a Python Result Object >>>

    The object itself has a main script and a property provider (e.g. enabling scoping methods) 

    After inserting the object, the property provider script was altered to include a geometry scoping possibility which may reduce the time needed for evaluation. The function reload_props() was replaced by following script 

    1. def reload_props():
    2.     this.PropertyProvider = None
    3.     provider = Provider()
    4.     group_one = provider.AddGroup("Group 1")
    5.     scoping_prop = group_one.AddProperty("Scoping Property", "Scoping", "property_templates")
    6.     this.PropertyProvider = provider

    Reload the properties for that object

    Then you should be able to select a geometric entity for that object.

    Afterwards replace the whole default main script with the following python snippet, whereas the part of the individual result file reference may need some adjustment.

    1.  def post_started(sender, analysis):# Do not edit this line
    2.     define_dpf_workflow(analysis)
    3.  
    4.  
    5. def define_dpf_workflow(analysis):
    6.     import mech_dpf
    7.     import Ans.DataProcessing as dpf
    8.     
    9.     #Utilizing geometry scoping > time reduction in calculation time
    10.     scoping_refs = this.GetCustomPropertyByPath("Group 1/Scoping Property/Geometry Selection").Value
    11.     mech_dpf.setExtAPI(ExtAPI)
    12.     nodes_loc = mech_dpf.GetNodeScopingByRefId(scoping_refs)
    13.     
    14.     #refering to the individual rst files
    15.     dataSource_a = dpf.DataSources()
    16.     dataSource_a.SetResultFilePath(analysis.ResultFileName) #the result file where the py result object was added to
    17.     dataSource_b = dpf.DataSources()
    18.     dataSource_b.SetResultFilePath(r'C:\...Mechanical\pyResultObject\StressRange_2023R1_files\dp0\SYS\MECH\file.rst')
    19.     #result file list which will be looped thru
    20.     data = [dataSource_a,dataSource_b] # [dataSource_a,dataSource_b,dataSource_c, ...]
    21.     
    22.     maxprin_fields = []
    23.     minprin_fields = []
    24.  
    25.  
    26.     #function to convert units if needed
    27.     def convert_unit(field,unit):
    28.         op = dpf.operators.math.unit_convert()
    29.         op.inputs.unit_name.Connect(unit)
    30.         op.inputs.entity_to_convert.Connect(field)
    31.         converted_field = op.outputs.converted_entity.GetDataT1()
    32.         return converted_field
    33.  
    34.  
    35.     #loop thru the individual result files
    36.     for i,rst in enumerate(data):
    37.         op = dpf.operators.metadata.time_freq_provider() # operator instanciation
    38.         op.inputs.data_sources.Connect(rst)
    39.         my_time_freq_support= op.outputs.time_freq_support.GetData() #get the time points in the result file
    40.         # read in min max principal stress for all time points
    41.         stress_prin1 = dpf.operators.result.stress_principal_1(data_sources=rst,mesh_scoping=nodes_loc)
    42.         stress_prin3 = dpf.operators.result.stress_principal_3(data_sources=rst,mesh_scoping=nodes_loc)
    43.  
    44.  
    45.         #loop thru the time points
    46.         for j,time in enumerate(my_time_freq_support.TimeFreqs.Data):
    47.             stress_prin1.inputs.time_scoping.Connect(time)
    48.             stress_prin3.inputs.time_scoping.Connect(time)
    49.             stress_prin1.inputs.mesh_scoping.Connect(nodes_loc)
    50.             stress_prin3.inputs.mesh_scoping.Connect(nodes_loc)
    51.             field_container_max = stress_prin1.outputs.fields_container.GetData()
    52.             field_container_min = stress_prin3.outputs.fields_container.GetData()
    53.             #create list of min and max stress
    54.             maxprin_fields.append(field_container_max[0])
    55.             minprin_fields.append(field_container_min[0])
    56.         
    57.         #create a field container holding all the data 
    58.         max_prin_field_container = dpf.FieldsContainerFactory.OverTimeFreqFieldsContainer(maxprin_fields)
    59.         min_prin_field_container = dpf.FieldsContainerFactory.OverTimeFreqFieldsContainer(minprin_fields)
    60.  
    61.  
    62.     # check unit systems if there is a mismatch the first entry will be utilized for converting
    63.     count=max_prin_field_container.FieldCount
    64.     for i in range(0,count):
    65.         if i ==0:
    66.             unit = max_prin_field_container[i].Unit
    67.         else:
    68.             if max_prin_field_container[i].Unit != unit:
    69.                 max_prin_field_container[i]=convert_unit(max_prin_field_container[i],unit)
    70.             if min_prin_field_container[i].Unit != unit:
    71.                 min_prin_field_container[i]=convert_unit(min_prin_field_container[i],unit)
    72.  
    73.  
    74.     #fetch the min and max over all time points of all provided result files
    75.     op = dpf.operators.min_max.min_max_by_entity() # operator instanciation
    76.     op.inputs.fields_container.Connect(max_prin_field_container)
    77.     my_field_max = op.outputs.field_max.GetData()
    78.     op.inputs.fields_container.Connect(min_prin_field_container)
    79.     my_field_min = op.outputs.field_min.GetData()
    80.     
    81.     #evaluate the range > delta_sigma =  simga_1 - simga_3
    82.     stress_range = dpf.operators.math.minus(fieldA=my_field_max,fieldB=my_field_min)
    83.  
    84.  
    85.     ############### Plotting
    86.     dpf_workflow = dpf.Workflow()
    87.     dpf_workflow.Add(stress_range)
    88.     dpf_workflow.SetOutputContour(stress_range.outputs.field.GetData(),dpf.enums.GFXContourType.GeomFaceScoping)
    89.     dpf_workflow.Record('wf_id', True)
    90.     this.WorkflowId = dpf_workflow.GetRecordedId()

    The last step would be to connect the script followed by ‘Evaluate All Results’

    The outcome will look like this S1(1072.064) – S3(-545.344) =delta_stress (1617.408) 


Welcome!

It looks like you're new here. Sign in or register to get started.