MecSimCalc
ExploreSearchCreateDocsCommunityBlogPricing
    Apps

    Starred
    Go to app
    App Docs

This page converts the Engineering stress-strain curve provided by the user to true stress-strain curve using the well known conversion equations. The user is required to input the strain value corresponding to the elasticity limit which the application uses to calculate Young's modulus as the slope of the initial elastic portion. The elasticity limit in this application is assumed to always be less than 0.005 and the user is required to input 8 data points beyond the initial zero point. The page also ouputs the stress-plastic strain data required by some finite element analysis software and provides the best-fit Ramberg-Osgood approximation to the given data.


The Code:


import matplotlib.pyplot as plt
import numpy as np
import base64
import io


#This function is used to create an image from the plot created using matplotlib.plt
def plt_show(plt, width=500, dpi=100):
    # Converts matplotlib plt to data string
    # dpi (dots per inch) is the resolution of the image
    # width is width of image in pixels
    bytes = io.BytesIO()
    plt.savefig(bytes, format='png', dpi=dpi)  # Save as png image
    plt.close()
    bytes.seek(0)
    base64_string = "data:image/png;base64," + \
        base64.b64encode(bytes.getvalue()).decode("utf-8")
    return ""



def main(inputs):
    elasticitylimit=inputs['elasticitylimit']
    stress=[inputs['stress_0'],inputs['stress_1'],inputs['stress_2'],inputs['stress_3'],inputs['stress_4'],inputs['stress_5'],inputs['stress_6'],inputs['stress_7'],inputs['stress_8']]
    strain=[inputs['strain_0'],inputs['strain_1'],inputs['strain_2'],inputs['strain_3'],inputs['strain_4'],inputs['strain_5'],inputs['strain_6'],inputs['strain_7'],inputs['strain_8']]
    
#    print(stress)
#    print(strain)
    n = len(stress)
    straine = [i for i in strain if i < elasticitylimit]
    stresse = [stress[i] for i in range(len(straine))]
    truestrain = [np.log(1.0 + i) for i in strain]
    truestress = [stress[i] * (1 + strain[i]) for i in range(len(strain))]
    # find Young's modulus
    p = np.polyfit(straine, stresse, 1)
    x = np.linspace(0, elasticitylimit)
    y = np.poly1d(p)
    E = y[1]
    #Young = "Young's modulus = " + str(round(E, 2)) + " (MPa)"
    Young=str(round(E,2))
    # find yield stress
    from scipy.interpolate import interp1d
    from scipy.optimize import root_scalar


    y1 = interp1d(truestrain, truestress, kind="linear")


    def g(x):
        return E * (x - 0.2 / 100) - y1(x)


    x2 = root_scalar(g, x0=0.5 / 100, x1=0.4 / 100)
    yield1 = (
        "Yield strength using 0.005 total strain criterion: "
        + str(np.round(y1(0.005), 2))
        + " (MPa)"
    )
    yield2 = (
        "Yield strength using 0.2% offset criterion: "
        + str(np.round(y1(x2.root), 2))
        + " (MPa)"
    )
    yield3 = "Yield strain using 0.2% offset criterion: " + str(np.round(x2.root, 4))
    yieldl = [yield1, yield2, yield3]
    x1 = np.linspace(0.002, 0.007)
    y1 = E * (x1 - 0.002)
    plasticstrain = [
        max(0, truestrain[i] - truestress[i] / E) for i in range(len(strain))
    ]
    plasticstrainzero = []
    for i in reversed(plasticstrain):
        plasticstrainzero.append(i)
        if i == 0:
            break
    plasticstrainzero.reverse()
    stresszero = truestress[len(truestress) - len(plasticstrainzero) : len(truestress)]
    # Ramberg Osgood in the form Keps^n
    from scipy.optimize import curve_fit
    plasticstrainzerocurve=plasticstrainzero
    stresszerocurve=stresszero


    if plasticstrainzero[0] == 0:
        plasticstrainzero = plasticstrainzero[1 : len(plasticstrainzero)]
        stresszero = stresszero[1 : len(stresszero)]


    def f(eps, k, n):
        return k * eps ** n


    coeff, covariance = curve_fit(f, plasticstrainzero, stresszero)
    x_val = np.arange(0, plasticstrainzero[-1], 0.001)
    y_val = f(x_val, coeff[0], coeff[1])
    rodatax = np.arange(0, plasticstrainzero[-1], 0.001)
    rodatay = f(rodatax, coeff[0], coeff[1])
    k = coeff[0]
    n = coeff[1]
    # R squared
    x = np.array(plasticstrainzero)
    y = np.array(stresszero)
    y_fit = f(x, coeff[0], coeff[1])
    ss_res = np.sum((y - y_fit) ** 2)
    ss_tot = np.sum((y - np.mean(y)) ** 2)
    r2 = 1 - (ss_res / ss_tot)
    #ROmessage = (
    #    "\(R^2\): "
    #    + str(round(r2, 3))
    #    + ", \(k\)= "
    #    + str(round(k, 2))
    #    + ", \(n\)= "
    #    + str(round(n, 5))
    #)
    ROmessage=[str(round(r2, 3)),str(round(k, 2)),str(round(n, 5))]
    # final curve
    import pandas as pd


    def eps(sigma):
        return sigma / E + (sigma / k) ** (1 / n)


    y_val = truestress
    x_val = [i / E + (i / k) ** (1 / n) for i in truestress]
    data = [
        (
            round(truestress[i], 2),
            round(truestrain[i], 4),
            round(plasticstrain[i], 4),
        )
        for i in range(len(strain))
    ]
    a = pd.DataFrame(
        data=data, columns=["True Stress", "True Strain", "Plastic Strain"]
    )
    xstrain = x2.root
    xelastic = [0.002, 0.007]
    xelasticyoung = [0, 0.005]
    yelastic = [0.0, E * (0.005)]
    smax = max(stress)
    rox = rodatax.tolist()
    roy = rodatay.tolist()
    ro = [rox, roy]
    curve = [strain, stress]
    truecurve = [truestrain, truestress] 
# Plotting the first Graph
    plt.plot(strain, stress,label="Engineering S-S Curve")
    plt.plot(truestrain,truestress,label="True S-S Curve")
    plt.legend(shadow=True, fancybox=True)
    plt.title("True and Engineering Stress-Strain Curves")
    plt.xlabel("Strain")
    plt.ylabel("Stress (MPa)")
    plt.xlim(xmin=0.0)
    plt.ylim(ymin=0.0)
    curve=plt_show(plt,500)
    plt.clf()
#Plot the elastic curve.
    plt.plot(truestrain,truestress,label="True S-S Curve")
    plt.plot(xelasticyoung,yelastic,label="Initial Linear Curve")
    plt.xlabel("Strain")
    plt.ylabel("Stress (MPa)")
    plt.xlim(xmin=0.0)
    plt.ylim(ymin=0.0)
    plt.legend(shadow=True, fancybox=True)
    ecurve=plt_show(plt,500)
    plt.clf()
#Plot the yield curve.
    plt.plot(truestrain,truestress,label="True S-S Curve")
    plt.plot(xelastic,yelastic,label="0.2% Offset Criterion")
    plt.plot([0.005,0.005],[0,smax],label="0.005 Strain Criterion")
    plt.xlabel("Strain")
    plt.ylabel("Stress (MPa)")
    plt.xlim(xmin=0.0)
    plt.ylim(ymin=0.0)
    plt.legend(shadow=True, fancybox=True)
    yieldcurve=plt_show(plt,500)
    plt.clf()
#Plot the plastic curve.
    plt.plot(plasticstrainzerocurve,stresszerocurve,label="Stress Plastic Strain Data")
    maxstrain=max(plasticstrainzerocurve)
    x1=np.linspace(0,maxstrain)
    plt.plot(x1,k*x1**n,label="Ramberg Osgood Idealization")
    plt.xlabel("Plastic Strain")
    plt.ylabel("Stress (MPa)")
    plt.xlim(xmin=0.0)
    plt.ylim(ymin=0.0)
    plt.legend(shadow=True, fancybox=True)
    plasticcurve=plt_show(plt,500)
    plt.clf()
#Plot the final curve.
    plt.plot(truestrain,truestress,label="True S-S Curve (Data)")
    maxstress=max(truestress)
    y1=np.linspace(0,maxstress)
    x1=y1/E+(y1/k)**(1/n)
    plt.plot(x1,y1,label="True S-S curve using the Ramberg Osgood idealization")
    plt.xlabel("Strain")
    plt.ylabel("Stress (MPa)")
    plt.xlim(xmin=0.0)
    plt.ylim(ymin=0.0)
    plt.legend(shadow=True, fancybox=True)
    finalcurve=plt_show(plt,500)
    plt.clf()
#    finalcurve = [x_val, y_val]
    tables = [a.to_html(justify="center", col_space="100px", header="True")]


 #   finalcurve = [x_val, y_val]
    tables = [a.to_html(justify="center", col_space="100px", header="True")]



    return{
        "curve":curve,
        "xstrain":xstrain,
        "ecurve":ecurve,
        "yieldcurve":yieldcurve,
        "yieldl":yieldl,
        "Young":Young,
        "plasticcurve":plasticcurve,
        "ROmessage":ROmessage,
        "ro":ro,
        "finalcurve":finalcurve,
        "tables":tables}


The Output Page:

Analysis Results:
The True Stress Strain Curve:
The true stress strain data calculated using the well known conversion equations is plotted with the Engineering stress strain curve in the following figure.
\varepsilon_{true}=\ln{\left(1+\varepsilon_{eng}\right)}
\sigma_{true}=\sigma_{eng}\left(1+\varepsilon_{eng}\right)
where:
\sigma_{true} and \sigma_{eng} are the true and engineering stresses while \varepsilon_{true} and \varepsilon_{eng} are the true and engineering strains.
{{outputs.curve|safe}}

Young's Modulus:
By fitting a straight line to the first few points in the data, Young's modulus can be estimated as the slope of the linear portion.
Young's modulus = {{outputs.Young}} MPa
{{outputs.ecurve|safe}}

Yield Strength:
Two different criteria can be used to estimate the yield strength of the material:
{{outputs.yieldl[0]}}
{{outputs.yieldl[1]}}
{{outputs.yieldl[2]}}
{{outputs.yieldcurve|safe}}

Ramberg Osgood Approximation:
The Ramberg Osgood Approximation used has the following form:
\varepsilon=\frac{\sigma}{E}+\left(\frac{\sigma}{k}\right)^n
where the stress is related to the plastic strain \varepsilon_p using the following equation:

\sigma=k \varepsilon_p^n

Using nonlinear curve fitting, the Ramberg Osgood Coefficients and the R^2 are equal to:
R^2= {{outputs.ROmessage[0]}}
k= {{outputs.ROmessage[1]}}
n= {{outputs.ROmessage[2]}}

The stress vs. plastic strain curve has the form:
{{outputs.plasticcurve|safe}}
The stress vs. strain curve using the Ramberg Osgood approximation has the form:
{{outputs.finalcurve|safe}}

Here is the final data:
{{outputs.tables|safe}}
Similar apps:
Engineering
Civil Engineering
Mechanical Engineering

Copyright © MecSimCalc 2025
Terms | Privacy