faulty stress data for 50CrMo4?

This commit is contained in:
Daniel G. Mevec 2025-04-06 19:46:30 +02:00
parent aeb99ef05e
commit b30f4cc7c4
38 changed files with 1634 additions and 0 deletions

View file

@ -0,0 +1,234 @@
# Veusz saved document (version 3.6.2)
# Saved at 2025-04-06T16:41:16.373686
SetCompatLevel(1)
AddImportPath('/home/dme/Documents/Diss/00_Schreiben/Diss/visualisation')
ImportFileCSV('data/stress_c38/A_Rohzustant_650/A10.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='A10_', rowsignore=1)
ImportFileCSV('data/stress_c38/A_Rohzustant_650/A12.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='A12_', rowsignore=1)
ImportFileCSV('data/stress_c38/A_Rohzustant_650/A13.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='A13_', rowsignore=1)
ImportFileCSV('data/stress_c38/A_Rohzustant_650/A14.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='A14_', rowsignore=1)
ImportFileCSV('data/stress_c38/A_Rohzustant_650/A15.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='A15_', rowsignore=1)
ImportFileCSV('data/stress_c38/A_Rohzustant_650/A16.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='A16_', rowsignore=1)
ImportFileCSV('data/stress_c38/A_Rohzustant_650/A1.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='A1_', rowsignore=1)
ImportFileCSV('data/stress_c38/A_Rohzustant_650/A2.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='A2_', rowsignore=1)
ImportFileCSV('data/stress_c38/A_Rohzustant_650/A3.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='A3_', rowsignore=1)
ImportFileCSV('data/stress_c38/A_Rohzustant_650/A4.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='A4_', rowsignore=1)
ImportFileCSV('data/stress_c38/A_Rohzustant_650/A6.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='A6_', rowsignore=1)
ImportFileCSV('data/stress_c38/A_Rohzustant_650/A8.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='A8_', rowsignore=1)
ImportFileCSV('data/stress_c38/A_Rohzustant_650/A9.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='A9_', rowsignore=1)
ImportFileCSV('data/stress_c38/Martensit/M3.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='M3_', rowsignore=1)
ImportFileCSV('data/stress_c38/Martensit/M5.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='M5_', rowsignore=1)
ImportFileCSV('data/stress_c38/Martensit/M6.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='M6_', rowsignore=1)
ImportFileCSV('data/stress_c38/Martensit/M7.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='M7_', rowsignore=1)
ImportFileCSV('data/stress_c38/Martensit/M8.csv', delimiter=';', headerignore=1, headermode='1st', linked=True, dsprefix='M8_', rowsignore=1)
Set('width', '9cm')
Set('height', '9cm')
Set('colorTheme', 'default-latest')
Set('StyleSheet/Font/font', 'CMU Serif')
Set('StyleSheet/Font/size', '8pt')
Set('StyleSheet/axis/MajorTicks/length', '4pt')
Set('StyleSheet/axis/MinorTicks/length', '2pt')
Set('StyleSheet/axis-function/autoRange', 'next-tick')
Set('StyleSheet/colorbar/autoRange', 'exact')
Set('StyleSheet/graph/leftMargin', '1.cm')
Set('StyleSheet/graph/rightMargin', '0.15cm')
Set('StyleSheet/graph/topMargin', '.15cm')
Set('StyleSheet/graph/bottomMargin', '0.85cm')
Set('StyleSheet/image/colorMap', 'parula')
Set('StyleSheet/key/keyLength', '5mm')
Set('StyleSheet/key/marginSize', 0.5)
Set('StyleSheet/page/width', '7cm')
Set('StyleSheet/page/height', '7cm')
Set('StyleSheet/xy/markerSize', '2.5pt')
Set('StyleSheet/xy/PlotLine/width', '1pt')
Set('StyleSheet/xy/MarkerLine/color', 'auto')
Set('StyleSheet/xy/MarkerFill/color', 'background')
Add('page', name='BASE', autoadd=False)
To('BASE')
Add('graph', name='graph1', autoadd=False)
To('graph1')
Add('axis', name='x', autoadd=False)
To('x')
Set('label', 'Strain [%]')
Set('max', 16.0)
To('..')
Add('axis', name='y', autoadd=False)
To('y')
Set('label', 'Stress [MPa]')
Set('direction', 'vertical')
To('..')
Add('key', name='key1', autoadd=False)
To('key1')
Set('horzPosn', 'right')
Set('vertPosn', 'bottom')
Set('horzManual', 0.0)
Set('vertManual', 0.0)
To('..')
Add('xy', name='xy1', autoadd=False)
To('xy1')
Set('marker', 'none')
Set('xData', 'A3_Dehnung')
Set('yData', 'A3_Standardkraft')
Set('key', '25°C')
To('..')
Add('xy', name='xy2', autoadd=False)
To('xy2')
Set('marker', 'none')
Set('xData', 'A2_Dehnung')
Set('yData', 'A2_Standardkraft')
Set('key', '100°C')
To('..')
Add('xy', name='xy3', autoadd=False)
To('xy3')
Set('marker', 'none')
Set('xData', 'A1_Dehnung')
Set('yData', 'A1_Standardkraft')
Set('key', '400°C')
To('..')
Add('xy', name='xy4', autoadd=False)
To('xy4')
Set('marker', 'none')
Set('xData', 'A4_Dehnung')
Set('yData', 'A4_Standardkraft')
Set('key', '500°C')
To('..')
Add('xy', name='xy5', autoadd=False)
To('xy5')
Set('marker', 'none')
Set('xData', 'A14_Dehnung')
Set('yData', 'A14_Standardkraft')
Set('key', '600°C')
To('..')
Add('xy', name='xy6', autoadd=False)
To('xy6')
Set('marker', 'none')
Set('xData', 'A6_Dehnung')
Set('yData', 'A6_Standardkraft')
Set('key', '700°C')
To('..')
To('..')
To('..')
Add('page', name='AUST', autoadd=False)
To('AUST')
Add('graph', name='graph1', autoadd=False)
To('graph1')
Add('axis', name='x', autoadd=False)
To('x')
Set('label', 'Strain [%]')
To('..')
Add('axis', name='y', autoadd=False)
To('y')
Set('label', 'Stress [MPa]')
Set('direction', 'vertical')
To('..')
Add('key', name='key1', autoadd=False)
To('key1')
Set('horzPosn', 'right')
Set('vertPosn', 'top')
To('..')
Add('xy', name='xy1', autoadd=False)
To('xy1')
Set('marker', 'none')
Set('xData', 'A13_Dehnung')
Set('yData', 'A13_Standardkraft')
Set('key', '600°C')
To('..')
Add('xy', name='xy7', autoadd=False)
To('xy7')
Set('marker', 'none')
Set('xData', 'A16_Dehnung')
Set('yData', 'A16_Standardkraft')
Set('key', '650°C')
To('..')
Add('xy', name='xy2', autoadd=False)
To('xy2')
Set('marker', 'none')
Set('xData', 'A12_Dehnung')
Set('yData', 'A12_Standardkraft')
Set('key', '700°C')
To('..')
Add('xy', name='xy3', autoadd=False)
To('xy3')
Set('marker', 'none')
Set('xData', 'A8_Dehnung')
Set('yData', 'A8_Standardkraft')
Set('key', '800°C')
To('..')
Add('xy', name='xy4', autoadd=False)
To('xy4')
Set('marker', 'none')
Set('xData', 'A15_Dehnung')
Set('yData', 'A15_Standardkraft')
Set('key', '900°C')
To('..')
Add('xy', name='xy5', autoadd=False)
To('xy5')
Set('marker', 'none')
Set('xData', 'A9_Dehnung')
Set('yData', 'A9_Standardkraft')
Set('key', '1000°C')
To('..')
Add('xy', name='xy6', autoadd=False)
To('xy6')
Set('marker', 'none')
Set('xData', 'A10_Dehnung')
Set('yData', 'A10_Standardkraft')
Set('key', '1100°C')
To('..')
To('..')
To('..')
Add('page', name='MART', autoadd=False)
To('MART')
Add('graph', name='graph1', autoadd=False)
To('graph1')
Add('axis', name='x', autoadd=False)
To('x')
Set('label', 'Strain [%]')
To('..')
Add('axis', name='y', autoadd=False)
To('y')
Set('label', 'Stress [MPa]')
Set('max', 2200.0)
Set('direction', 'vertical')
To('..')
Add('key', name='key1', autoadd=False)
To('key1')
Set('vertPosn', 'bottom')
To('..')
Add('xy', name='xy1', autoadd=False)
To('xy1')
Set('marker', 'none')
Set('xData', 'M8_Dehnung')
Set('yData', 'M8_Standardkraft')
Set('key', '26°C')
To('..')
Add('xy', name='xy2', autoadd=False)
To('xy2')
Set('marker', 'none')
Set('xData', 'M7_Dehnung')
Set('yData', 'M7_Standardkraft')
Set('key', '100°C')
To('..')
Add('xy', name='xy3', autoadd=False)
To('xy3')
Set('marker', 'none')
Set('xData', 'M6_Dehnung')
Set('yData', 'M6_Standardkraft')
Set('key', '200°C')
To('..')
Add('xy', name='xy4', autoadd=False)
To('xy4')
Set('marker', 'none')
Set('xData', 'M5_Dehnung')
Set('yData', 'M5_Standardkraft')
Set('key', '300°C')
To('..')
Add('xy', name='xy5', autoadd=False)
To('xy5')
Set('marker', 'none')
Set('xData', 'M3_Dehnung')
Set('yData', 'M3_Standardkraft')
Set('key', '350°C')
To('..')
To('..')
To('..')

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,2 @@
.venv/
output/

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View file

@ -0,0 +1,3 @@
Proben-ID m{lo E} R{lo p0.1} R{lo p0.2} R{lo m} A{lo g} A Z
GPa MPa MPa MPa % % %
"RT" 204 504 505 721 10,3 22,7 61

Binary file not shown.

After

Width:  |  Height:  |  Size: 996 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View file

@ -0,0 +1,6 @@
Werkstoff Proben-ID m{lo E} R{lo p0.1} R{lo p0.2} R{lo m} A{lo g} A A{lo manuell} Z d{lo 0} L{lo 0} T Dauer
GPa MPa MPa MPa % % % % mm mm °C min
"50CrMo4" "Pr5" 196 429 451 721 12,5 28,2 65 7,98 30,00 300 20
"50CrMo4" "Pr2" 198 406 424 617 8,8 33,8 78 7,98 30,00 400 20
"50CrMo4" "Pr3" 194 352 378 477 4,5 36,9 86 7,98 30,00 500 20
"50CrMo4" "Pr4" 129 289 309 329 1,5 44,1 93 7,98 30,00 600 20

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View file

@ -0,0 +1,3 @@
Proben-ID m{lo E} R{lo p0.1} R{lo p0.2} R{lo eH} R{lo eL} R{lo m} A{lo g} A Z
GPa MPa MPa MPa MPa MPa % % %
"RT" 208 438 434 438 434 813 10,1 20,6 55

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,013 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View file

@ -0,0 +1,6 @@
Werkstoff Proben-ID m{lo E} R{lo p0.1} R{lo p0.2} R{lo m} A{lo g} A A{lo manuell} Z d{lo 0} L{lo 0} T Dauer
GPa MPa MPa MPa % % % % mm mm °C min
"50CrMo4" "Pr1" 181 302 347 820 11,9 34,7 75 7,99 30,00 300 20
"50CrMo4" "Pr2" 177 293 328 681 8,4 32,9 83 7,99 30,00 400 20
"50CrMo4" "Pr3" 172 277 303 528 5,8 37,1 90 7,99 30,00 500 20
"50CrMo4" "Pr4" 182 232 253 354 3,8 52,5 86 7,98 30,00 600 20

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,292 @@
# -*- coding: utf-8 -*-
"""Convert Stress-Strain Tables to true values.
This Skript takes a stress-strain table or a collection of such and converts
the technical strains into true strains.
It is also capable of outputting comparison graphs of the converted tables.
"""
import os, sys, re
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def parse_args():
import argparse
parser = argparse.ArgumentParser(description='Convert Stress-Strain Tables to true plastic flow values.',
usage='python %(prog)s [options] INPUTFILE [-o OUTPUTFILE]',
epilog='''
''')
parser.add_argument('input',
metavar='INPUTFILE',
help='path to input file containing stress-strain data')
parser.add_argument('-v', '--version',
action='version',
version='%(prog)s 1.1')
parser.add_argument('-e',
action='store_true',
dest='autodetect_emod',
help='enables autodetection of Young\'s modulus. (currently nonfunctional)')
group0 = parser.add_mutually_exclusive_group()
group0.add_argument('-c',
action='store_true',
dest='compressionflag',
help='set computation for compressive test data.')
group0.add_argument('-n',
action='store_false',
dest='cut_at_uts',
help='extend computation of tensile data beyond ultimate tensile strength.')
parser.add_argument('-N',
action='store_false',
dest='cut_neg_slope',
help='allow exported data to have a negative slope (may cause errors in FEM).')
parser.add_argument('-x',
metavar = 'SCALE',
default = 1.0,
type = float,
dest='scale_x',
help='set scaling factor for X data. Defaults to 1.')
parser.add_argument('-y',
metavar = 'SCALE',
default = 1.0,
type = float,
dest='scale_y',
help='set scaling factor for Y data. Defaults to 1.')
parser.add_argument('-p',
action='store_true',
dest='plotflag',
help='plot transformation steps from technical to true flow curves.')
parser.add_argument('-P',
action='store_true',
dest='comparisonflag',
help='plot comparison of true flow curves.')
group = parser.add_mutually_exclusive_group()
group.add_argument('-r',
metavar=('X', 'Y'),
type=float,
nargs=2,
dest='range_man',
help='''set global plot range in X-axis (strain, dimensionless)
and Y-axis (stress, MPa).''')
group.add_argument('-a',
action='store_true',
dest='range_auto',
help='''determine global plot range automatically.''')
parser.add_argument('-o',
metavar='OUTPUTFILE',
type=str,
dest='output',
help='output file path')
parser.add_argument('-s',
action='store_true',
dest='serial',
help='concatinates all curves for import into Abaqus.')
parser.add_argument('-t',
metavar = 'LENGTH',
default = 0,
type = int,
dest='output_length',
help='constrain output to a maximum length.')
return parser.parse_args()
def sanitize_title(s):
"""turns a unicode or string into a purely alphanumeric string."""
return str(s.encode('ascii', 'ignore').decode())
def reduce_lenth(data):
num_split = args.output_length
assert num_split>2
first = data[0]
last = data[-1]
rest = data[1:-1]
subs = np.array_split(rest, num_split-2)
short = np.array([a.mean() for a in subs if a.size!=0])
return np.insert(short, [0,len(short)], [first, last])
if __name__=="__main__":
args = parse_args()
inpath = os.path.abspath(args.input)
datafile = pd.ExcelFile(inpath)
sheets = datafile.sheet_names
frames = {sheet:datafile.parse(sheet) for sheet in sheets}
if args.output:
outpath = os.path.abspath(args.output)
outfilename, ext = os.path.splitext(outpath)
else:
outpath = outfilename = ext = False
if args.range_man:
xmax, ymax = args.range_man
if args.range_auto:
xmax = 0
ymax = 0
for frame in frames.values():
e_data, sig_data = np.transpose(frame.values)[:2] * np.array([args.scale_x, args.scale_y])
xmax = max(xmax, np.max(np.abs(e_data)))
ymax = max(ymax, np.max(sig_data*(e_data + 1)))
xmax = 1.05 * xmax
ymax = 1.05 * ymax
e_max_global = 0
s_max_global = 0
df_dict = {}
for title, frame in frames.items():
print(title)
temp = sanitize_title(title)
e_data, sig_data, Emod = np.transpose(frame.values)[:3]
Emod = Emod[0] * args.scale_y
e_tech = e_data * args.scale_x
sig_tech = sig_data * args.scale_y
assert np.sign(np.median(sig_tech)) == np.sign(np.median(e_tech)), "Stress and strain do not seem to share sign!"
if Emod not in (np.inf, -np.inf, 0):
e_tech_plastic = e_tech - e_tech[0] - sig_tech/Emod
else:
e_tech_plastic = e_tech
try:
idx_plastic = np.where(e_tech_plastic < 0)[0][-1]
except IndexError:
idx_plastic = 0
if args.compressionflag:
e_true = -np.log(1 - e_tech)
e_true_plastic = -np.log(1 - e_tech_plastic)
sig_true = sig_tech * (1 - e_tech)
idx_ultimate = -1
else:
e_true = np.log(1 + e_tech)
e_true_plastic = np.log(1 + e_tech_plastic)
sig_true = sig_tech * (1 + e_tech)
if args.cut_at_uts:
smax = np.max(sig_tech)
idx_ultimate = np.where(sig_tech == smax)[0][0]
else:
idx_ultimate = -1
sig_slice = sig_true[idx_plastic:idx_ultimate]
e_slice = e_true_plastic[idx_plastic:idx_ultimate]
if args.cut_neg_slope:
idx_negative_slope = [i for i in range(len(sig_slice)) if i != np.argmax(sig_slice[0:i+1])]
sig_slice = np.delete(sig_slice, idx_negative_slope)
e_slice = np.delete(e_slice, idx_negative_slope)
e_slice[0] = 0
if args.output_length > 0:
e_slice = reduce_lenth(e_slice)
sig_slice = reduce_lenth(sig_slice)
e_max_global = max(e_max_global, np.max(e_slice))
s_max_global = max(s_max_global, np.max(sig_slice))
df_dict[temp] = pd.DataFrame({'Sig':sig_slice, 'Eps':e_slice})
if args.plotflag:
plt.figure(figsize=[5, 2.8])
plt.plot(e_tech, sig_tech/args.scale_y, 'g')
plt.plot(e_true, sig_true/args.scale_y, 'r')
plt.plot(e_true[idx_plastic:idx_ultimate], sig_true[idx_plastic:idx_ultimate]/args.scale_y, 'k')
plt.plot(e_slice, sig_slice/args.scale_y, 'b')
plt.title(title)
plt.ylabel(r'$\sigma$ [MPa]')
plt.xlabel(r'$\epsilon$ [-]')
if args.range_auto or args.range_man:
plt.ylim(0, ymax)
plt.xlim(0, xmax)
plt.grid(True, which='major', linestyle='--')
plt.grid(True, which='minor', linestyle=':')
# plt.axes().set_aspect('equal')
if outpath:
plotpath = '{}_{}.png'.format(os.path.splitext(outpath)[0],temp)
plt.savefig(plotpath, bbox_inches="tight", dpi=144)
else:
plt.show()
plt.close()
if args.comparisonflag:
plt.figure(figsize=[5, 2.8])
for temp, frame in df_dict.items():
e_frame = frame['Eps']
sig_frame = frame['Sig']
plt.plot(e_frame, sig_frame/args.scale_y, label=temp)
plt.title('True Stress-Strain Curves')
plt.ylabel(r'$\sigma$ [MPa]')
plt.xlabel(r'$\epsilon$ [-]')
if args.range_auto or args.range_man:
plt.ylim(0, ymax)
plt.xlim(0, xmax)
else:
plt.ylim(0, s_max_global/args.scale_y*1.05)
plt.xlim(0, e_max_global*1.05)
plt.grid(True, which='major', linestyle='--')
plt.grid(True, which='minor', linestyle=':')
plt.legend(loc='lower right')
# plt.axes().set_aspect('equal')
if outpath:
plotpath = outfilename + '.png'
plt.savefig(plotpath, bbox_inches="tight", dpi=144)
else:
plt.show()
plt.close()
if args.output and args.serial:
frame_out = pd.DataFrame(columns=['Sig', 'Eps', 'T'])
for temp, frame in df_dict.items():
nums = re.findall(r"[-+]?\d*\.\d+|\d+", temp)
try:
frame['T'] = int(nums[0])
except ValueError:
frame['T'] = float(nums[0])
except IndexError as e:
raise e('Could not extract number from frame title to use as temperature!')
frame_out = frame_out.append(frame, ignore_index=True, sort=False)
frame_out.sort_values(by=['T', 'Eps'], inplace=True)
frame_out = frame_out.reindex(columns=['Sig', 'Eps', 'T'])
if ext and ext.lower() in ['.xls', '.xlsx']:
frame_out.to_excel(outpath,index=False)
else:
frame_out.to_csv(outpath,index=False)
elif args.output:
if ext and ext.lower() in ['.xls', '.xlsx']:
with pd.ExcelWriter(outpath) as writer:
for temp, frame in df_dict.items():
frame.to_excel(writer, sheet_name=temp,
index=False)
else:
for temp, frame in df_dict.items():
newpath = ("_{}".format(temp)).join(os.path.splitext(outpath))
frame.to_csv(newpath ,index=False)
else:
pass #frame_out.to_csv(sys.stdout,index=False)