Analýza dat z tahového diagramu#

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from lmfit import Model
%matplotlib inline

Dva datové soubory .xls obsahující data z tahové zkoušky jsme získali z věřejně přístupných zdrojů. Popisují naměřená data při zkoušce oceli 1045 slitiny hliníku 6061.

Načtení dat z Excelu#

Nejdříve si pomocí funkce %ls ověříme, že nás adresář obsahuje data z měření. Tato funkce nám vypíše obsah adresáře.

Pomocí funkce pd.read_excel() z balíčku pandas je možné přímo načíst data. Data ze dvou excelových souborů budou uložena ve dvou datových objektech nazvaných steel_df a al_df. Datový objekt pandas je tabulkový datový typ.

K zobrazení prvních pěti řádků každého datového rámce můžeme použít metodu .head().

%ls ../data/ 
df_al = pd.read_excel('../data/Al60601_raw_data.xls')
df_al.head()
Al60601_raw_data.xls  Steel1018_raw_data.xls
WARNING *** OLE2 inconsistency: SSCS size is 0 but SSAT size is non-zero
TESTNUM POINTNUM TIME POSIT FORCE EXT CH5 CH6 CH7 CH8
0 542 1 8.470 0.02256 201.146011 -0.001444 0.007552 NaN NaN NaN
1 542 2 8.632 0.02330 206.599442 0.000302 0.007552 NaN NaN NaN
2 542 3 10.027 0.02846 287.512573 0.003044 0.018898 NaN NaN NaN
3 542 4 11.031 0.03232 365.380981 0.009881 0.022061 NaN NaN NaN
4 542 5 11.928 0.03616 447.813965 0.014085 0.033652 NaN NaN NaN
df_steel = pd.read_excel('../data/Steel1018_raw_data.xls')
df_steel.head()
WARNING *** OLE2 inconsistency: SSCS size is 0 but SSAT size is non-zero
TESTNUM POINTNUM TIME POSIT FORCE EXT CH5 CH6 CH7 CH8
0 523 1 6.189 0.07302 202.924728 0.000402 -0.028272 NaN NaN NaN
1 523 2 6.549 0.07396 205.714890 -0.000238 -0.034549 NaN NaN NaN
2 523 3 7.148 0.07624 217.763336 -0.000713 -0.030140 NaN NaN NaN
3 523 4 9.146 0.08438 316.306122 0.002377 -0.025968 NaN NaN NaN
4 523 5 10.041 0.08822 417.003357 0.003089 -0.024100 NaN NaN NaN

Vidíme, že naměřená data obashují různé hodnoty. Pro nás je nejdůležitejší sloupec síla (FORCE). Kromě těchto hodnot máme k dispozici ještě hodnotu EXT hodnoty prodloužení z mechanického extenzometeru v % a CH5, který obsahuje hodnoty prodloužení z laserového extensometru v %.

Úprava dat#

Protože tato data jsme získali z americké laboratoře, máme sílu určenou v librách (pounds) a průmer zkušební tyče je 0.506 palců (inch). Nejdříve musíme tyto hodnoty převést na jednotky SI.

  • Pro převod síly nebo hmotnosti z liber (lb) na newtony (N) použijeme následující vztah: 1 lb \(\approx\) 4,4822162 N.

  • Pro převod délky z palců (inch) na milimetry (mm) použijeme následující vztah: 1 inch = 25.4 mm.

Note

Síla v N, rozměry v mm, napětí v MPa $\(1 \frac{\mathrm{N}}{\mathrm{mm}^2} = 1\,10^6 \frac{\mathrm{N}}{\mathrm{m}^2} = 1 \mathrm{MPa}\)$

d = 0.506 * 25.4 # mm
force_al = df_al['FORCE'].to_numpy() *  4.4822162#N
force_steel = df_steel['FORCE'].to_numpy() * 4.4822162 #N

Následně si určíme smluvné napětí vydělením síly počátečným průřezem a převedem prodloužení z procent. Protože laserový exntezometr je přesnější, budeme počítat s těmito daty.

A = np.pi*d**2/4
stress_al = force_al / A
stress_steel = force_steel/A

strain_al = df_al['CH5'].to_numpy()*0.01
strain_steel = df_steel['CH5'].to_numpy()*0.01

Vykreslení závislosti#

Nyní, když máme data z tahového testu připravena, můžeme vytvořit rychlý graf pomocí metody ax.plot() knihovny Matplotlib. První pár hodnot (x, y), který předáme do ax.plot(), je ( strain_al}, stress_al), a druhý pár (x, y), který předáme, je (strain_steel, stress_steel). Příkaz plt.show() zobrazí graf.

fig,ax = plt.subplots()

ax.plot(strain_al, stress_al, strain_steel, stress_steel)

plt.show()
../_images/0f15dea8873f7ac009714efd9393a4a82d346d6f373785d39d8c16879cec4c28.png

Náš graf vylepšíme přidáním popisek jednotlivých křivek a os.

Matplotlib metoda

Popis

Příklad

ax.set_xlabel()

popisek osy x

plt.xlabel(‘strain (in/in)’)

ax.set_ylabel()

popisek osy y

plt.ylabel(‘stress (ksi)’)

ax.set_title()

poisek grafu

plt.title(‘Stress Strain Curve’)

ax.legend()

legenda

plt.plt(x,y, label=’steel’)

fig,ax = plt.subplots()

ax.plot(strain_al, stress_al)
ax.plot(strain_steel, stress_steel)

ax.set_xlabel('Poměrná deformace (m/m)')
ax.set_ylabel('Napětí (MPa)')
ax.set_title('Smluvní tahový diagram  slitiny hliníku 6061 a oceli 1018')
ax.legend(['Al6061','Steel1018'])

plt.show()
../_images/8380842d82a3796dd8cc00b045f37a1ba881e955758c6861305b3028c7736d0f.png

Nyní můžeme uložit graf jako obrázek ve formátu .png pomocí metody plt.savefig() knihovny Matplotlib. Kód níže vytvoří graf a uloží obrázek s názvem tahovy_diagram.png. Argument dpi=300 uvnitř metody plt.savefig() specifikuje rozlišení uloženého obrázku. Obrázek bude uložen ve složce static stejného adresáře jako náš kód.

fig,ax = plt.subplots()

ax.plot(strain_al, stress_al, label = 'Al6061')
ax.plot(strain_steel, stress_steel, label = 'Steel1018')

ax.set_xlabel('Poměrná deformace (m/m)')
ax.set_ylabel('Napětí (MPa)')
ax.set_title('Smluvní tahový diagram  slitiny hliníku 6061 a oceli 1018')
ax.legend()

plt.savefig('static/tahovy_diagram.png', dpi=300)
plt.show()
../_images/8380842d82a3796dd8cc00b045f37a1ba881e955758c6861305b3028c7736d0f.png

Nalezení meze pevnosti#

Mez pevnosti je bod na grafu s největší hodnotou napětí.

uts_steel = np.max(stress_steel)
uts_al = np.max(stress_al)

Pro vykreslení dodáme ještě deformace, ve kterých nastává mez pevnosti

uts_strain_steel = strain_steel[stress_steel==uts_steel][0]
uts_strain_al = strain_al[stress_al==uts_al][0]



print(f'Mez pevnosti pro hliník 6061 je {uts_al} MPa a nastává při poměrném prodloužení {uts_strain_al}.')
print(f'Mez pevnosti pro ocel 1018 je {uts_steel} MPa a nastává při poměrném prodloužení {uts_strain_steel}.')
Mez pevnosti pro hliník 6061 je 328.87169171951257 MPa a nastává při poměrném prodloužení 0.10797487258911133.
Mez pevnosti pro ocel 1018 je 663.4758721964481 MPa a nastává při poměrném prodloužení 0.12940356254577637.

Body si můžeme přidat do grafu.

fig,ax = plt.subplots()

ax.plot(strain_al, stress_al, label = 'Al6061')
ax.plot(strain_steel, stress_steel, label = 'Steel1018')

ax.plot(uts_strain_al, uts_al, "o", label = '$\sigma_P$ Al6061')
ax.plot(uts_strain_steel, uts_steel, "o", label = '$\sigma_P$ ocel 1018')


ax.set_xlabel('Poměrná deformace (m/m)')
ax.set_ylabel('Napětí (MPa)')
ax.set_title('Smluvní tahový diagram  slitiny hliníku 6061 a oceli 1018')
ax.legend()

plt.savefig('static/tahovy_diagram.png', dpi=300)
plt.show()
../_images/3f88991d1c9ffd3fef3595356c66f0b6809d64eeec348d3fa99bccd3367a6cbe.png

Určení Youngova modulu pružnosti#

Zvolíme si část křivky, pro kterou je průběh lineárrní. Pro slitinu hliníku to bude přibližně oblast mezi 0 a 250 MPa a pro ocel mezi 0 a 350 MPa.

lin_stress_steel = stress_steel[stress_steel<350]
lin_strain_steel = strain_steel[stress_steel<350]

lin_stress_al = stress_al[stress_al<250]
lin_strain_al = strain_al[stress_al<250]

fig,ax = plt.subplots()

ax.plot(lin_strain_al, lin_stress_al, label = 'Al6061')
ax.plot(lin_strain_steel, lin_stress_steel, label = 'Steel1018')

ax.set_xlabel('Poměrná deformace (m/m)')
ax.set_ylabel('Napětí (MPa)')
ax.set_title('Smluvní tahový diagram  slitiny hliníku 6061 a oceli 1018')
ax.legend()
<matplotlib.legend.Legend at 0x73e1dd2eb010>
../_images/393a5ddde4781d65e5f8a9c74e43e5a552246befcced642cf46c6253f21727e0.png

V jednoduchém přístupu použijeme funkci aproximace bodů polynomem prvního stupně.

param_steel = np.polyfit(lin_strain_steel, lin_stress_steel, 1)
param_al = np.polyfit(lin_strain_al, lin_stress_al, 1)

print(f'Ocel 1018: Napětí = {param_steel[1]} + {param_steel[0]} * deformace')
print(f'Al6061: Napětí = {param_al[1]} + {param_al[0]} * deformace')
Ocel 1018: Napětí = 30.353246542441244 + 267660.33488346846 * deformace
Al6061: Napětí = -13.32484752659266 + 68493.0090973414 * deformace

A zpětné získáme fitovaná data.

fit_stress_steel = np.polyval(param_steel, lin_strain_steel)
fit_stress_al = np.polyval(param_al, lin_strain_al)

fig,ax = plt.subplots()

ax.plot(lin_strain_al, lin_stress_al, label = 'Al6061')
ax.plot(lin_strain_steel, lin_stress_steel, label = 'Steel1018')
ax.plot(lin_strain_al, fit_stress_al,"--" ,label = 'fit Al6061')
ax.plot(lin_strain_steel, fit_stress_steel,"--", label = 'fit Steel1018')

ax.set_xlabel('Poměrná deformace (m/m)')
ax.set_ylabel('Napětí (MPa)')
ax.set_title('Smluvní tahový diagram  slitiny hliníku 6061 a oceli 1018')
ax.legend()
<matplotlib.legend.Legend at 0x73e1dd366020>
../_images/2692cf927593bb1eff8a6bbea050c5b23a5e734138f8f721865fc8158c138661.png

Sklon přímky nám udáva hodnotu Youngova modulu pružnosti.

print(f'E(ocel 1018) = {param_steel[0]/1000} GPa')
print(f'E(Al6061) = {param_al[0]/1000} GPa')
E(ocel 1018) = 267.66033488346847 GPa
E(Al6061) = 68.4930090973414 GPa

Výsledky můžeme srovnat s výsledky v tabulkách, např. matweb.com nebo asm.matweb.com. Na základě našich měření a hodnot v tabulkách se můžeme pokusit odhadnout o jaký typ zpracování oceli 1018 se jedná.

Alternativou je využití složitějších modelů k fitování křivek, například knihovna lmfit.

def model_hooke(epsilon, E):
    return epsilon * E

emodel = Model(model_hooke)

result = emodel.fit(lin_stress_steel, epsilon=lin_strain_steel, E=0*1e3)

print(result.fit_report())

plt.plot(lin_strain_steel, lin_stress_steel, 'o')
plt.plot(lin_strain_steel, result.init_fit, '--', label='initial fit')
plt.plot(lin_strain_steel, result.best_fit, '-', label='best fit')
plt.legend()
plt.show()

print(f'E(ocel 1018) = {result.params["E"]/1000} GPa')
[[Model]]
    Model(model_hooke)
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 13
    # data points      = 91
    # variables        = 1
    chi-square         = 139374.949
    reduced chi-square = 1548.61055
    Akaike info crit   = 669.399783
    Bayesian info crit = 671.910643
    R-squared          = 0.84966458
[[Variables]]
    E:  307574.304 +/- 6556.48153 (2.13%) (init = 0)
../_images/5b5a6ee2804b97e35782aed1ff0a1b9b69a987cda22d7f52b6e1d677a31eb1c8.png
E(ocel 1018) = 307.57430351056655 GPa