# Is it possible to consider temperature dependent strength data for safety factor calculation?

Options
Member, Employee Posts: 2

Is it possible to consider temperature dependent strength data for safety factor calculation within the stress tool?

Tagged:

• Member, Employee Posts: 2
Options

It is possible via a Python Result object inside Mechanical. The following script calculates the safety factor considering temperature dependent limit stresses:

```def post_started(sender, analysis):# Do not edit this line
define_dpf_workflow(analysis)

def LinearInterpolation(x,x1,y1,x2,y2):
# Simple linear interpolation
# Returns -1 if x is outside of [x1,x2]
if x<x1 or x>x2:
return -1 # out of range
if y1==y2:
return y1
else:
a=(y2-y1)/(x2-x1)
b=y1-a*x1
return a*x+b

def GetLimitStress(temperature,stress_data):
# Find limit stress value for a given temperature
# This is done by simple linear interpolation between two
# points of a limit stress/temperature curve

# Find closest temperature in stress_data
num_points=len(stress_data)/2
for i in range(num_points):
temp=stress_data[2*i]
if temp>temperature:
index=i
break
# Get temperature/limit stress points between which to interpolat
if index!=num_points:
x2=stress_data[index*2]
x1=stress_data[(index-1)*2]
y2=stress_data[index*2+1]
y1=stress_data[(index-1)*2+1]
else:
return -2 # temperature value is out of bounds

return LinearInterpolation(temperature,x1,y1,x2,y2) # return limit stress

def GetLimitStressField(stress,temperatures,stress_data):
# From a field of stresses and temperatures, find limit stress
# at each node. Stress_data defines the limit stress/temperature curve
import mech_dpf
import Ans.DataProcessing as dpf

stress_nodes=stress.outputs.getfields_container()[0].ScopingIds
limit_field=dpf.FieldsFactory.CreateScalarField(1,'Nodal')

local_temp=temperatures.outputs.getfields_container()[0]

for nid in stress_nodes:
temp=local_temp.GetEntityDataById(nid)[0]

return limit_field

def define_dpf_workflow(analysis):
import mech_dpf
import Ans.DataProcessing as dpf

# Define limit stress data as list in form of [temp1,limit_stress1,temp2,limit_stress2,...])
limit_stress_data=[-100.,200.,0.,220.,50.,210.,100,200.,1000.,150.]

my_data_sources = dpf.DataSources(analysis.ResultFileName)
my_time_scoping = dpf.Scoping()
my_time_scoping.Ids = [1] # the first set

# Retrieve structural temperature at nodes
temperature=dpf.operators.result.structural_temperature(requested_location='Nodal')
temperature.inputs.data_sources.Connect(my_data_sources)
temperature.inputs.time_scoping.Connect(my_time_scoping)

# Retrieve Mises stress at nodes
s_eqv_op = dpf.operators.result.stress_von_mises()
s_eqv_op.inputs.requested_location.Connect('Nodal')
s_eqv_op.inputs.data_sources.Connect(my_data_sources)
s_eqv_op.inputs.time_scoping.Connect(my_time_scoping)

# Retrieve limit_stress for each node based on Mises and temperature
limit_stress=GetLimitStressField(s_eqv_op,temperature,limit_stress_data)

# Divide limit stress by Mises stress
limit_factor=dpf.operators.math.component_wise_divide()
limit_factor.inputs.fieldA.Connect(limit_stress)
limit_factor.inputs.fieldB.Connect(s_eqv_op)

dpf_workflow = dpf.Workflow()
dpf_workflow.SetOutputContour(limit_factor)
dpf_workflow.Record('wf_id', True)
this.WorkflowId = dpf_workflow.GetRecordedId()
```
• Member, Employee Posts: 283
Options

Only for clarification and full context, I wanted to point out that mechanical has this general capability via a stress tool post processing object that will plot factors of safety that are temperature dependent based on material property.

This forum is for scripted solutions, so obviously the solution is on point, and it is a good starting point for implementing more complex or specific processing routines, then what is offered in a native solution.

• Member, Moderator, Employee Posts: 810
Options

My understanding is that Mechanical's stress tool will indeed take into account temperature-dependent stress (as we can define E = f(T)),

but natively it is not possible to define that the Tensile Yield Stress is temperature-dependent:

which is what the code from @Patrick Herberich does.

• Member, Moderator, Employee Posts: 810
Options

Piggybacking on this solution. I've slightly modified the code so that instead of having the Yield Strenght vs Temp values hard-coded, they are read from a comma delimited csv file placed in the user_files directory of the project.

Code is:

```def post_started(sender, analysis):# Do not edit this line
define_dpf_workflow(analysis)

def user_files_directory():
user_files = ''

if ExtAPI.Context == 'Project':
user_files = GetUserFilesDirectory()
elif ExtAPI.Context == 'Mechanical':
import wbjn
user_files = wbjn.ExecuteCommand(ExtAPI, "returnValue(GetUserFilesDirectory())")
return user_files

def LinearInterpolation(x,x1,y1,x2,y2):
# Simple linear interpolation
# Returns -1 if x is outside of [x1,x2]
if x<x1 or x>x2:
return -1 # out of range
if y1==y2:
return y1
else:
a=(y2-y1)/(x2-x1)
b=y1-a*x1
return a*x+b

def GetLimitStress(temperature,stress_data):
# Find limit stress value for a given temperature
# This is done by simple linear interpolation between two
# points of a limit stress/temperature curve

# Find closest temperature in stress_data
num_points=len(stress_data)/2
for i in range(num_points):
temp=stress_data[2*i]
if temp>temperature:
index=i
break
# Get temperature/limit stress points between which to interpolat
if index!=num_points:
x2=stress_data[index*2]
x1=stress_data[(index-1)*2]
y2=stress_data[index*2+1]
y1=stress_data[(index-1)*2+1]
else:
return -2 # temperature value is out of bounds

return LinearInterpolation(temperature,x1,y1,x2,y2) # return limit stress

def GetLimitStressField(stress,temperatures,stress_data):
# From a field of stresses and temperatures, find limit stress
# at each node. Stress_data defines the limit stress/temperature curve
import mech_dpf
import Ans.DataProcessing as dpf

stress_nodes=stress.outputs.getfields_container()[0].ScopingIds
limit_field=dpf.FieldsFactory.CreateScalarField(1,'Nodal')

local_temp=temperatures.outputs.getfields_container()[0]

for nid in stress_nodes:
temp=local_temp.GetEntityDataById(nid)[0]

return limit_field

def get_stress_data():
import csv
import os
limit_stress_data = []
user_dir = user_files_directory()
if os.path.exists(os.path.join(user_dir, 'TemperatureDependentYieldStrength.csv')):
with open(os.path.join(user_dir, 'TemperatureDependentYieldStrength.csv')) as csv_file:
line_count = 0
if line_count == 0:
line_count += 1
else:
limit_stress_data.append(float(row[0]))
limit_stress_data.append(float(row[1]))
line_count += 1
else:
msg = Ansys.Mechanical.Application.Message('Temperature Dependent Yield Strenght file does not exist', MessageSeverityType.Error)
return limit_stress_data

def define_dpf_workflow(analysis):
import mech_dpf
import Ans.DataProcessing as dpf

# Define limit stress data as list in form of [temp1,limit_stress1,temp2,limit_stress2,...])
limit_stress_data = get_stress_data()

my_data_sources = dpf.DataSources(analysis.ResultFileName)
my_time_scoping = dpf.Scoping()
my_time_scoping.Ids = [1] # the first set

# Retrieve structural temperature at nodes
temperature=dpf.operators.result.structural_temperature(requested_location='Nodal')
temperature.inputs.data_sources.Connect(my_data_sources)
temperature.inputs.time_scoping.Connect(my_time_scoping)

# Retrieve Mises stress at nodes
s_eqv_op = dpf.operators.result.stress_von_mises()
s_eqv_op.inputs.requested_location.Connect('Nodal')
s_eqv_op.inputs.data_sources.Connect(my_data_sources)
s_eqv_op.inputs.time_scoping.Connect(my_time_scoping)

# Retrieve limit_stress for each node based on Mises and temperature
limit_stress=GetLimitStressField(s_eqv_op,temperature,limit_stress_data)

# Divide limit stress by Mises stress
limit_factor=dpf.operators.math.component_wise_divide()
limit_factor.inputs.fieldA.Connect(limit_stress)
limit_factor.inputs.fieldB.Connect(s_eqv_op)

dpf_workflow = dpf.Workflow()