Lista de Exercícios 6   Gravação Aula 6 (24/09/2021)   Gravação Aula 6 (25/02/2022) Ajuda
   Sumário ×
×

Essa página tem como objetivo servir de material de apoio para a aula de módulo de Weibull. Ela apresenta widgets interativos que em teoria carregam automaticamente. Entretanto, pode ser necessário clicar no botão abaixo para carregá-los:


Show widgets

ATENÇÃO: Pode demorar até 5 minutos para carregar devidamente todos os widgets. Se eles não estiverem respondendo à sua interação, reinicie a página.

Se tiver alguma falha técnica ou dúvida, por favor, não hesite em contactar:

Murilo Henrique Moreira - E-mail: moreira.murilo@gmail.com

#@title 
# HIDDEN
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from ipywidgets import interactive, widgets
from matplotlib.ticker import FormatStrFormatter
from scipy import stats
from IPython.core.display import HTML, clear_output
import pandas as pd
pd.set_option('display.max_rows', None)
%matplotlib inline
HTML("""
<style>
.output_png {
    display: table-cell;
    text-align: center;
    vertical-align: middle;
}
.output{align-items: center;}
</style>
""")
# HIDDEN
mpl.rcParams.update({'font.size': 22})
#@title 
def run_test(epsilon_i, E, sigma_f):
    if epsilon_i * E < sigma_f:
        epsilons = np.linspace(0, epsilon_i, 1000)
        sigmas = E*epsilons
    else:
        epsilons = np.linspace(0, epsilon_i, 1000)
        sigmas = E*epsilons
        sigmas[sigmas>sigma_f] = np.zeros(sigmas[sigmas>sigma_f].shape[0])
    return epsilons, sigmas

def hide_code_in_slideshow():   
    from IPython import display
    import binascii
    import os
    uid = binascii.hexlify(os.urandom(8)).decode()    
    html = """<div id="%s"></div>
    <script type="text/javascript">
        $(function(){
            var p = $("#%s");
            if (p.length==0) return;
            while (!p.hasClass("cell")) {
                p=p.parent();
                if (p.prop("tagName") =="body") return;
            }
            var cell = p;
            cell.find(".input").addClass("hide-in-slideshow")
        });
    </script>""" % (uid, uid)
    display.display_html(html, raw=True)

Estatística de Weibull - Uma Ferramenta de Conversão e Comparação de Comportamentos Mecânicos

test

Introdução

Alguns exemplos de aplicação da estatística de Weibull:

  • Usada para a definição de apólice de seguros e planos de saúde
  • Na previsão climática (na distrbiuição de velocidade dos ventos)
  • Na Teoria de Valores Extremos (os "Cisnes Negros")
  • Estimativa do tempo de vida de componentes de elevada importância (Oleodutos, dutos e brocas para extração de petróleo e gás e até mesmo componentes da Estação Espacial Internacional)
  • Em situações onde elevada reprodutibilidade do comportamento é fundamental (próteses, componentes aeronáuticos, transportes de alta velocidade)

O comportamento mecânico dos materiais é fundamental para sua aplicação segura, seja em componentes de máquinas, ou quando usado como material estrutural.

Sendo assim, caracterizá-lo é de grande importância:

test

Figura 1: Ensaio de Flexão de Alumina e um vidro sodalime.

Em um ensaio, aplica-se a carga (ou deslocamento) no material, até atingir sua falha. Esta é caracterizada (para materiais frágeis fraturando de forma catastrófica) como a queda repentina da tensão.

#@title 
# HIDDEN

m=3
E=400e9
sigma_0=220e6
sigma_f_1 = 220e6  # np.random.weibull(m, 1)*sigma_0
mpl.rcParams.update({'font.size': 22})

def f(epsilon_i):
    epsilons_1, sigmas_1 = run_test(epsilon_i, E, sigma_f_1)
    epsilon_max = sigma_f_1/E
    bar = np.array([0.09, 0.1, 0.11])
    plt.figure(figsize=(6.5, 6.5))
#     plt.text(0.0925, 215, 'Amostra')
#     plt.text(bar[0]*(1-epsilon_i*100)*0.9, 205, 'F')
#     plt.text(bar[2]*(1+epsilon_i*100)*1.06, 205, 'F')

#     plt.arrow(bar[0]*(1-epsilon_i*100), 200, -0.01, 0, head_width=10, head_length=0.005,
#               fc='k', ec='k', zorder=4)
#     plt.arrow(bar[2]*(1+epsilon_i*100), 200, 0.01, 0, head_width=10, head_length=0.005,
#               fc='k', ec='k', zorder=4)
#     if epsilon_i < epsilon_max:
#         plt.plot([bar[0]*(1-epsilon_i*100), bar[1],
#                   bar[2]*(1+epsilon_i*100)], [200, 200, 200], lw=10, c='k', label='Amostra')
#     if epsilon_i >= epsilon_max:
#         plt.plot([bar[0]*(1-epsilon_i*100),
#                   bar[1]*(1-(epsilon_i-epsilon_max)*100)-0.0021], [200, 200], lw=10, c='k')
#         plt.plot([bar[1]*(1+(epsilon_i-epsilon_max)*100)+0.0021,
#                   bar[2]*(1+epsilon_i*100)], [200, 200], lw=10, c='k', label='Amostra')
    plt.plot(epsilons_1*100, sigmas_1*1e-6, c='Navy', lw=5)
    plt.ylim(0, 300)
    plt.xlim(0, 0.14e-2*100)
    plt.ylabel('Tensão, $\sigma$ [MPa]')
    plt.xlabel('Deformação, $\epsilon$ [%]')
    plt.grid(lw=0.25)
#     plt.legend(borderpad=1.2)
    plt.show()

int_plot = interactive(f,
#                        epsilon_i=(0, 1e-4, 0.1e-5),
                         epsilon_i=widgets.FloatSlider(value=0,
                                                       min=0,
                                                       max=1e-3,
                                                       step=2e-5,
                                                       description='$\epsilon$',
                                                       readout_format='.2e',
                                                       orientation='horizontal')
                      )
output = int_plot.children[-1]
output.layout.height = '630px'
int_plot.layout = widgets.Layout(display='flex',
                               flex_flow='column-reverse',
                               align_items='center',
                               align_content='center',
                               justify_content='center',
                               width='100%')
int_plot

Widget 1: Ensaio de Flexão 3-Pontos de uma Alumina.

Mas onde o material falhou?

Uma maneira de responder essa pergunta é através da análise das tensões em um corpo sujeito a flexão em 3 pontos.

Isto pode ser feito de maneira analítica (como na disciplina Mecânica dos Sólidos) ou de maneira numérica como através da simulação por elementos finitos abaixo:

test

Figura 2: Simulação de Elementos Finitos de um Ensaio Flexão. Mapa de calor da tensão no material.

Este resultado pode ser avaliado também pela deformação no corpo de prova, como também é possível observar na malha deformada abaixo:

test

Figura 3: Simulação de Elementos Finitos de um Ensaio Flexão. Mapa de calor da tensão no material, considerando deformação (exagerada).

Isso vale para um material perfeito (sem defeitos), porém, devemos lembrar que os defeitos são intrínsecos ao material! Sendo assim, a pergunta contínua:

Onde o material falhou?

Lembrando que defeitos concentram tensões, não é só o local da falha, mas também a resistência mecânica que dependerá das suas posições e características. Como exemplo, consideremos 3 possíveis defeitos: test

O material pode romper em alguns possíveis cenários como:

  • Romper na superfície inferior, onde a tração é máxima, assim que alcançar o limite
  • Romper no defeito 1, caso a combinação de tensão trativa local, geometria e tamanho do defeito resultarem no $\sigma_{th}$
  • Romper no defeito 2
  • Romper no defeito 3

Em síntese:

O valor de resistência mecânica vai depender dos seguintes fatores:

  1. Tamanho (e geometria) do defeito
  2. Posição do defeito no corpo
  3. Orientação do defeito relativa ao corpo

Todas estas características serão dependentes de fatores determinísticos (parâmetros de processamento, matérias-primas, aditivos, ...), e estocásticos e assim, dentro de uma amostragem de $n$ corpos de um mesmo material teremos uma distribuição de valores de resistência mecânica.

Assim, temos três consequências principais:

  • O uso do $\sigma_f$ médio não é apropriado para projetos de estruturas ou componentes
  • A probabilidade de falha de uma peça maior é maior do que o de uma peça menor (comparação entre amostras de diferentes áreas)
  • O valor de resistência mecânica obtido depende da técnica utilizada (já que diferentes técnicas solicitam diferentes volumes do material em tração)

Dessa forma, apresentaremos ferramentas estatísticas para tratar estes dados e poder quantificar o comportamento geral de um dado material.

Começaremos com uma breve revisão estatística e em seguida introduziremos análises passíveis de serem feitas usando estas ferramentas e os conceitos já vistos no curso.

Distribuições Estatísticas

Começemos considerando uma distribuição de uma variável contínua, no caso uma amostragem de 10000 pessoas nas quais se perguntou a sua altura. Nós podemos visualizar o resultado através de um histograma:

# HIDDEN

fig = plt.figure(figsize=(8, 8))
mu_3 = 173.1
sigma_3 = 2.74
plt.hist(stats.norm.rvs(loc=mu_3, scale=sigma_3, size=10000), 100, color='green', zorder=3, label=f'$\mu={mu_3}$cm, $\sigma={sigma_3}$cm')

plt.ylabel('Frequência')
plt.xlabel('Altura [cm]')

plt.legend(fontsize=14)
plt.grid()
plt.show()

Figura 5: Resultados de uma pesquisa feita com 10000 pessoas sobre suas alturas.

Esta distribuição pode ser descrita por dois valores, a média, $\mu$ e o desvio padrão, $\sigma$. Seus efeitos no perfil do histograma de distribuição pode ser visto abaixo:

#@title 
# HIDDEN

mu_3 = 173.1
sigma_3 = 7.5
dist_3 = stats.norm.rvs(loc=mu_3, scale=sigma_3, size=10000)
def f(sigma_1, mu_1):
    plt.figure(figsize=(6.5, 6.5))
    plt.hist(dist_3, color='green', zorder=3, 
             bins=np.arange(110, 250 + 2, 2),
             label=f'$\mu={mu_3}$cm, $\sigma={round(sigma_3**0.5, 2)}$cm')
    plt.hist(stats.norm.rvs(loc=mu_1, scale=sigma_1**2, size=10000),
             color='navy', zorder=3, 
             bins=np.arange(110, 250 + 2, 2),
             label=f'$\mu={mu_1}$cm, $\sigma={round(sigma_1, 2)}$cm', alpha=0.5)

    plt.ylabel('Frequência')
    plt.xlabel('Altura [cm]')
    
    plt.legend(fontsize=14)
    plt.grid()
    plt.show()

int_plot = interactive(f,
#                        epsilon_i=(0, 1e-4, 0.1e-5),
                         mu_1=widgets.FloatSlider(value=173.1,
                                                       min=120,
                                                       max=210,
                                                       step=5,
                                                       description='$\mu$',
                                                       orientation='horizontal'),
                       sigma_1=widgets.FloatSlider(value=2.74,
                                                       min=0.25,
                                                       max=5.5,
                                                       step=0.25,
                                                       description='$\sigma$',
                                                       orientation='horizontal')
                      )
output = int_plot.children[-1]
output.layout.height = '630px'
int_plot.layout = widgets.Layout(display='flex',
                               flex_flow='column-reverse',
                               align_items='center',
                               align_content='center',
                               justify_content='center',
                               width='100%')
int_plot

Widget 2: Efeitos dos parâmetros de uma distribuição normal.

Nós podemos aproximar os dados coletados por uma curva de distribuição (ou função) de densidade de probabilidade, a FDP, levando a espessura da barra para zero.

Outra forma de visualizar estes resultados é através da função de distribuição acumulada, a FDA, que apresenta qual a fração da amostra que tem um valor igual ou menor do que determinado valor.

# HIDDEN

xs = np.linspace(150, 205, 1000)
fig, axs = plt.subplots(1, 2, figsize=(16, 6))
mu_3 = 173.1
sigma_3 = 7.5
normal_3 = stats.norm(loc=mu_3, scale=sigma_3)
axs[1].plot(xs, normal_3.cdf(xs), c='green', lw=4,
            label=f'$\mu={mu_3}$cm, $\sigma={round(sigma_3**0.5, 2)}$cm')
axs[0].hist(normal_3.rvs(1000), density=True, bins=80, zorder=0)
axs[0].plot(xs, normal_3.pdf(xs), c='green', lw=4,
            label=f'$\mu={mu_3}$cm, $\sigma={round(sigma_3**0.5, 2)}$cm')


axs[1].set_ylabel('Função de Distribuição \n Acumulada (FDA)')
axs[0].set_ylabel('Função Densidade de \n Probabilidade (FDP)')


for ax in axs:
    ax.set_xlabel('Altura [cm]')
    ax.grid()
    ax.legend(fontsize=12)
plt.tight_layout(w_pad=2)
plt.show()

Figura 6: Exemplos de distribuição normal com diferentes parâmetros de localização (média) e escala (desvio padrão), apresentados pela Função de Distribuição Acumulada e Função Densidade de Probabilidade.

Efeito dos Parâmetros em uma Distribuição Normal

#@title 
# HIDDEN

mu_3 = 173.1
sigma_3 = 7.5
xs = np.linspace(100, 250, 1000)
cdf_3 = stats.norm.cdf(xs, loc=mu_3, scale=sigma_3)
pdf_3 = stats.norm.pdf(xs, loc=mu_3, scale=sigma_3)
def f(sigma_1, mu_1):
    fig, axs = plt.subplots(1, 2, figsize=(18, 8))
    axs[1].plot(xs, cdf_3, c='Navy', lw=2,
                label=f'$\mu={mu_3}$cm, $\sigma={round(sigma_3**0.5, 2)}$cm')
    axs[0].plot(xs, pdf_3, c='Navy', lw=2,
                label=f'$\mu={mu_3}$cm, $\sigma={round(sigma_3**0.5, 2)}$cm')
    axs[1].plot(xs, stats.norm.cdf(xs, loc=mu_1, scale=sigma_1**2), c='red', lw=2,
                label=f'$\mu={mu_1}$cm, $\sigma={round(sigma_1, 2)}$cm')
    axs[0].plot(xs, stats.norm.pdf(xs, loc=mu_1, scale=sigma_1**2), c='red', lw=2,
                label=f'$\mu={mu_1}$cm, $\sigma={round(sigma_1, 2)}$cm')
    axs[1].set_ylabel('Função de Distribuição \n Acumulada (FDA)')
    axs[0].set_ylabel('Função Densidade de \n Probabilidade (FDP)')
    for ax in axs:
        ax.set_xlabel('Altura [cm]')
        ax.legend(loc='upper left', fontsize=14)
        ax.grid()
    plt.tight_layout()
    plt.show()

int_plot = interactive(f,
#                        epsilon_i=(0, 1e-4, 0.1e-5),
                          sigma_1=widgets.FloatSlider(value=2.74,
                                                       min=0.25,
                                                       max=5.5,
                                                       step=0.25,
                                                       description='$\sigma$',
                                                       orientation='horizontal', layout={'fontsize': 20}),
                          
                       mu_1=widgets.FloatSlider(value=173.1,
                                                       min=120,
                                                       max=210,
                                                       step=5,
                                                       description='$\mu$',
                                                       orientation='horizontal')
                      )
output = int_plot.children[-1]
output.layout.height = '450px'
int_plot.layout = widgets.Layout(display='flex',
                               flex_flow='column-reverse',
                               align_items='center',
                               align_content='center',
                               justify_content='center',
                               width='100%')
int_plot

Widget 3: Efeitos dos parâmetros de uma distribuição normal na sua FDP e FDA.

Estas funções podem ser interpoladas dos dados experimentais

Devido o fato de que um grande número de fenômenos serem representados por um pequeno número de funções analíticas, estas ditribuições possuem nomes próprios:

  • Distribuição normal (Gaussiana)
  • Distribuição de Pareto
  • Distribuição Logística
  • Distribuição de Cauchy
  • Distribuição de Boltzmann
  • Distribuição de Weilbull

A Distribuição de Weibull

A função de distribuição de Weibull é definida pela seguinte função de distribuição acumulada:


\begin{equation} P_{f}(\sigma)=\left\{\begin{array}{ll} 1-e ^{-\left(\frac{\sigma-\sigma_{u}}{\sigma_{0}}\right)^{m}} & \sigma>\sigma_{u} \\ 0 & \sigma \leq \sigma_{u} \end{array}\right. \end{equation}

E sua função densidade de probabilidade é dada por:


\begin{equation} p(\sigma)=\left\{\begin{array}{ll} - \frac{m}{\sigma_{0}} \left(\frac{\sigma-\sigma_{u}}{\sigma_{0}}\right)^{m-1} e ^{-\left(\frac{\sigma-\sigma_{u}}{\sigma_{0}}\right)^{m}} & \sigma>\sigma_{u} \\ 0 & \sigma \leq \sigma_{u} \end{array}\right. \end{equation}

Os gráficos a seguir demonstram a sua FDP e FDA:

#@title
# HIDDEN

sigma = np.linspace(0,50, 1000)
m = 15
sigma_0 = 20
weibull_pdf = lambda sigma, m, sigma_0: (m/sigma_0)*(sigma/sigma_0)**(m-1)*np.exp(-(sigma/sigma_0)**m)
weibull_cdf = lambda sigma, m, sigma_0: 1-np.exp(-(sigma/sigma_0)**m)
fig, axs = plt.subplots(1, 2, figsize=(18, 8))
ax1, ax2 = axs
ax1.plot(sigma, weibull_pdf(sigma, 50, 20), c='Navy', label='$\sigma_0$ =20,  m = 50')
ax2.plot(sigma, weibull_cdf(sigma, 50, 20), c='Navy', label='$\sigma_0$ =20,  m = 50', lw=1, ls='--')
ax1.plot(sigma, weibull_pdf(sigma, 5, 20), c='red', label='$\sigma_0$ =20, m = 5')
ax2.plot(sigma, weibull_cdf(sigma, 5, 20), c='red', label='$\sigma_0$ =20, m = 5', lw=1, ls='--')


# ax1.set_ylabel('Probability Density Function')
# ax2.set_ylabel('Cumulative Distribution Function')
ax2.set_ylabel('Função de Distribuição\n  Acumulada (FDA)')
ax1.set_ylabel('Função Densidade \n de Probabilidade (FDP)')
for ax in [ax1, ax2]:
    ax.set_xlim(0,50)
    ax.set_ylim(0,1.05)
    ax.legend(fontsize=14)
    ax.grid()

plt.tight_layout()
plt.show()

Figura 7: Exemplos de distribuição de Weibull com diferentes parâmetros apresentados pela Função de Distribuição Acumulada e Função Densidade de Probabilidade.

Por que usar a distribuição de Weibull?

A distribuição de Weibull é qualitativamente próxima de uma distribuição normal:

#@title 
# HIDDEN

sigma = np.linspace(0,50, 1000)
m = 15
sigma_0 = 20
weibull_pdf = lambda sigma, m, sigma_0: (m/sigma_0)*(sigma/sigma_0)**(m-1)*np.exp(-(sigma/sigma_0)**m)
weibull_cdf = lambda sigma, m, sigma_0: 1-np.exp(-(sigma/sigma_0)**m)
fig, axs = plt.subplots(1, 2, figsize=(18, 6))
ax1, ax2 = axs
ax1.plot(sigma, stats.weibull_min.pdf(sigma, 20, 0, 20), c='Navy', label='Weibull - $\sigma_0$ =20 MPa,  m = 20')
ax2.plot(sigma, stats.weibull_min.cdf(sigma, 20, 0, 20), c='Navy', label='Weibull - $\sigma_0$ =20 MPa,  m = 20', lw=1, ls='--')
ax1.plot(sigma, stats.norm.pdf(sigma, 20, 1.206**0.5), c='red', label='Normal - $\mu$ =20 MPa, $\sigma$ = 1.099')
ax2.plot(sigma, stats.norm.cdf(sigma, 20, 1.206**0.5), c='red', label='Normal - $\mu$ =20 MPa, $\sigma$ = 1.099', lw=1, ls='--')


# ax1.set_ylabel('Probability Density Function')
# ax2.set_ylabel('Cumulative Distribution Function')
ax2.set_ylabel('Função de Distribuição\n  Acumulada (FDA)')
ax1.set_ylabel('Função Densidade \n de Probabilidade (FDP)')
for ax in [ax1, ax2]:
    ax.set_xlim(12.5, 25)
    ax.set_ylim(0,1.05)
    ax.legend(loc='upper left', fontsize=16)
    ax.grid()
ax1.set_ylim(0,0.450)
plt.tight_layout()
plt.show()
#

Figura 8: Comparação de uma distribuição Normal e uma distribuição de Weibull.

Então, por que usar a distribuição de Weibull?

  • Em primeiro lugar, a distribuição normal é consideravelmente mais complexa:
Distribuição FDP FDA
Weibull \begin{equation} p(\sigma)=\left\{\begin{array}{ll} \frac{m}{\sigma_0} \left(\frac{\sigma-\sigma_{u}}{\sigma_0}\right)^{m-1} e ^{-\left(\frac{\sigma-\sigma_u}{\sigma_{0}}\right)^{m}} & \sigma>\sigma_{u} \notag \\ 0 & \sigma \leq \sigma_{u} \end{array}\right. \end{equation} \begin{equation} P_{f}(\sigma)=\left\{\begin{array}{ll} 1-e ^{-\left(\frac{\sigma-\sigma_{u}}{\sigma_{0}}\right)^{m}} & \sigma>\sigma_{u} \notag \\ 0 & \sigma \leq \sigma_{u} \end{array}\right. \end{equation}
Normal \begin{equation} p(x) = \frac{1}{2}\left[1+\operatorname{erf}\left(\frac{x-\mu}{\varsigma \sqrt{2}}\right)\right] \notag \end{equation} \begin{equation} P(x) = \frac{1}{\varsigma \sqrt{2 \pi}} e^{-\frac{1}{2}\left(\frac{x-\mu}{\varsigma}\right)^{2}}\notag \end{equation}

Isto seria problemático para as etapas posteriores da Análise de Weibull!

  • Em segundo lugar, observe que a distribuição normal admite valores negativos para a resistência mecânica!

Efeito dos Parâmetros na Distribuição de Weibull

#@title 
# HIDDEN


m = 15
sigma_0 = 20

def weibull_view_1(m, sigma_0):
    weibull_pdf = lambda sigma, m, sigma_0: (m/sigma_0)*(sigma/sigma_0)**(m-1)*np.exp(-(sigma/sigma_0)**m)
    weibull_cdf = lambda sigma, m, sigma_0: 1-np.exp(-(sigma/sigma_0)**m)
    sigmas = np.linspace(0, 150, 1000)
    fig, axs = plt.subplots(1, 2, figsize=(18, 8))
    axs[0].plot(sigmas, weibull_pdf(sigmas, m, sigma_0), c='Navy', label=f'$\sigma_0$ = {sigma_0},  m = {m}')
    axs[0].set_xlim(0, 50)
#     axs[0].set_ylim(0, 5)
    axs[0].set_xlabel('Tensão, $\sigma$ [MPa]')
    axs[0].set_ylabel('Função Densidade  \n de Probabilidade (FDP)')
    axs[1].plot(sigmas, weibull_cdf(sigmas, m, sigma_0), c='Navy', label=f'$\sigma_0$ = {sigma_0},  m = {m}')
    axs[1].set_xlim(0, 50)
#     axs[1].set_ylim(0, 1.25)
    axs[1].set_xlabel('Tensão, $\sigma$ [MPa]')
    axs[1].set_ylabel('Função de Distribuição \n Acumulada (FDA)')
    plt.tight_layout()
    
    for ax in axs:
        ax.yaxis.set_major_formatter(FormatStrFormatter('%.2f'))
        ax.grid()
        ax.legend()
    plt.show()

int_plot = interactive(weibull_view_1,
                       sigma_0=widgets.FloatSlider(value=5,
                                                       min=5,
                                                       max=45,
                                                       step=1,
                                                       description='$\sigma_0$',
                                                       readout_format='.2f'),
                       m=widgets.FloatSlider(value=2,
                                                       min=2,
                                                       max=200,
                                                       step=5,
                                                       description='$m$',
                                                       readout_format='.2f')
                      )
output = int_plot.children[-1]
output.layout.height = '450px'
int_plot.layout = widgets.Layout(display='flex',
                               flex_flow='column-reverse',
                               align_items='center',
                               align_content='center',
                               justify_content='center',
                               width='100%')
int_plot

Widget 4: Efeitos dos parâmetros de uma distribuição de Weibull na sua FDP e FDA.

Qual o sentido físico dos parâmetros de Weibull?

Análise de Weibull Aplicada na Resistência Mecânica do Material

test

Figura 9: Da Vinci e representação de sua teoria.

A análise de Weibull é inspirada na Teoria do Elo Mais Fraco (proposta por Aristóteles e revisitada por Leonardo Da Vinci):

"Uma corrente é tão forte quanto o for o seu elo mais fraco."

"Quanto maior a corrente, maior a é a probabilidade de que ela falhe quando uma carga é aplicada."

Esta teoria considera fraturas frágeis em uma escala macroscópica.

Todo material solicitado por uma carga está sujeito a uma probabilidade de falha, $P_f$

Esta, pode ser representada matematicamente como:

\begin{equation} P_f = 1 - P_S \end{equation}

Onde $P_S$ é a probabilidade de sobrevivência do material.

Nós podemos assumir estas quantias como funções da tensão ao qual o material está sujeito, $\sigma$ e devido a teoria do elo mais fraco, do volume $V$:

\begin{equation} P_f(\sigma, V) = 1 - P_s(\sigma, V) \end{equation}

Para conduzir a análise, consideremos o que ocorre em um determinado corpo de volume $V + \delta V$. Este corpo apenas sobreviverá se ambas as partes, $V$ e $\delta V$ sobreviverem, isto é, precisamos considerar a probabilidade combinada de ambos os cenários. Matematicamente:

\begin{equation} P_s(\sigma, V + \delta V) = P_s(\sigma, V) \ P_s(\sigma, \delta V) \end{equation}

Se considerarmos que a distribuição de probabilidades de uma pequena parte do corpo $\delta V$ falhar é descrita por uma densidade de porbabilidade $\varphi(\sigma)$ (isto é, uma função que retorna o valor de probabilidade de um volume infinitesimal falhar para uma dada aplicação de uma tensão local $\sigma$), temos:

\begin{equation} P_s(\sigma, \delta V) = 1 - P_f(\sigma, \delta V) = 1 - \varphi(\sigma) \ \delta V \end{equation}

Substituindo na Equação 5, e rearranjando temos: \begin{equation} \frac{P_{s}(\sigma, V+\delta V)-P_{s}(\sigma, V)}{\delta V}=-\varphi(\sigma) \ P_{s}(\sigma, V) \end{equation}

Se reduzirmos o valor de $\delta V$ podemos aproximar a derivada da probabilidade de sobrevivência em função do volume:

\begin{equation} \frac{\partial P_s(\sigma, V)}{\partial V} = - \varphi(\sigma) \ P_s(\sigma, V) \end{equation}

Lembrando que a tensão depende da posição e integrando é possível obter $P_s$:

\begin{equation} P_{s}(\sigma, V) = \exp \left\{-\int_{V} \varphi[\sigma(\mathbf{r})] d V\right\} \end{equation}

Usando a Equação 3, podemos achar a probabilidade de falha como sendo: \begin{equation} P_{f}(\sigma, V)=1-P_{s}(\sigma, V)= 1 -\exp \left\{-\int_{V} \varphi[\sigma(\mathbf{r})] d V\right\} \end{equation}

Para um caso mais simples no qual a tensão independe da posição (por exemplo na caso de uma amostra em tração uniaxial), a Equação 10 se torna: \begin{equation} P_{f}(\sigma, V)=1-P_{s}(\sigma, V) =1-\exp \left\{- V \ \varphi(\sigma) \right\} \end{equation}

Weibull assumiu que $\varphi(\sigma)$ tinha a seguinte forma:

\begin{equation} \varphi(\sigma)=\left(\frac{\sigma}{\Sigma_{0}}\right)^{m} \end{equation}

Finalmente chegando que $P_f$ é dado por:

\begin{equation} P_f = 1 - \exp\left[-V \left(\frac{\sigma}{\Sigma_0}\right)^m\right] \end{equation}

Que é a função de distribuição acumulada de Weibull com parâmetro de escala $\sigma_0$ dado por:

\begin{equation} \sigma_0 = \frac{\Sigma_0}{V^{\frac{1}{m}}} \end{equation}

Efeito do Volume

Nós iremos avaliar o efeito do volume de uma amostra, usando a probabilidade de falha. Da Equação 13, para uma amostra $a$ de um determinado material com volume $V_a$ e tensão de ruptura $\sigma_a$, temos:

\begin{equation} P_{f,a} = 1 - \exp\left[-V_a \left(\frac{\sigma_a}{\Sigma_0}\right)^m\right] \end{equation}

De maneira análoga para uma amostra $b$ do mesmo material temos: \begin{equation} P_{f,b} = 1 - \exp\left[-V_b \left(\frac{\sigma_b}{\Sigma_0}\right)^m\right] \end{equation}

Podemos considerar um mesmo valor de probabilidade de falha igualando as Equações 15 e 16:

\begin{equation} \exp\left[-V_a \left(\frac{\sigma_a}{\Sigma_0}\right)^m\right] = \exp\left[-V_b \left(\frac{\sigma_b}{\Sigma_0}\right)^m\right] \end{equation}

Se aplicarmos $-\log$ em ambos os lados temos:

\begin{equation} V_a \left(\frac{\sigma_a}{\Sigma_0}\right)^m = V_b \left(\frac{\sigma_b}{\Sigma_0}\right)^m \end{equation}

Como $\Sigma_0$ independe do volume, podemos cortar o $\left(\frac{1}{\Sigma_0}\right)^m$ de ambos os lados, chegando assim em:

\begin{equation} V_a \sigma_a^m = V_b \sigma_b^m \end{equation}

E rearranjando temos: \begin{equation} \frac{\sigma_a}{\sigma_b} = \left(\frac{V_b}{V_a}\right)^\frac{1}{m} \end{equation}

É possível comparar tais quantias em um gráfico, podemos ver o efeito de reduzir o tamanho da amostra:

# HIDDEN

VbVa = np.logspace(1, -5, 1000)
m_1 = 1
m_2 = 10
m_3 = 100
m_4 = 500
fig = plt.figure(figsize=(12, 9))
plt.plot(VbVa, VbVa**(1/m_1), c='navy', label=f'm={m_1}', lw=3)
plt.plot(VbVa, VbVa**(1/m_2), c='orangered', label=f'm={m_2}', lw=3)
plt.plot(VbVa, VbVa**(1/m_3), c='y', label=f'm={m_3}', lw=3)
plt.plot(VbVa, VbVa**(1/m_4), c='k', label=f'm={m_4}', lw=3)
plt.ylim(-0.2, 1.05)
plt.xlim(1, 1e-5)
plt.gca().set_xscale('log')
plt.text(0.002, 0.15, 'Aumentando o valor de $m$ $\longrightarrow$', rotation=50)

plt.ylabel(r'$\frac{\sigma_a}{\sigma_b}$')
plt.xlabel(r'$\frac{V_b}{V_a}$')
plt.text(0.02, -0.15, 'Diminuindo $V_b$ →')
plt.text(0.8, -0.175, '← Aumentando $\sigma_b$', rotation=90)

plt.legend(loc='lower right', fontsize=14)
plt.grid()
plt.show()

Figura 10: Efeito do módulo de Weibull na relação volume da amostra e tensão de ruptura medida.

Efeito do Ensaio

Nós podemos considerar o efeito do Ensaio na resistência mecânica considerando a forma mais geral da Probabilidade de falha, dada na Equação 10, e considerando a que a tensão pode ser descrita como:

\begin{equation} \sigma(\mathbf{r})=\sigma_{\max } g(\mathbf{r}) \end{equation}

Substituindo na Equação 10, temos: \begin{equation} P_{f}=1-\exp \left[-\left(\frac{\sigma_{\max }}{\Sigma_{0}}\right)^{m} \int_{V} g^{m}(\mathbf{r}) d V\right] \end{equation}

E assim podemos definir o fator do ensaio $k\le1$:

\begin{equation} k=\frac{1}{V} \int_{V} g^{m}(\mathbf{r}) d V \quad \quad \quad \text { ou } \quad \quad \quad k=\frac{1}{V} \int_{V}\left(\frac{\sigma(\mathbf{r})}{\sigma_{\max }}\right)^{m} d V \end{equation}

Dessa maneira temos que a Equação 22 pode ser reescrita como: \begin{equation} P_{f}=1-\exp \left[-k V\left(\frac{\sigma_{\max }}{\Sigma_{0}}\right)^{m}\right] \end{equation}

Calculando o fator do ensaio de tração para um paralelepípedo com volume $V= a \ b \ c$ temos que $\sigma(\mathbf{r})=\sigma_{max}$ e portanto $k_t$ é dado por:

\begin{equation} k_t = \frac{1}{V} \int_V 1 dV = \frac{1}{V} \iiint dx dy dz = \frac{a \ b \ c}{V} = 1 \end{equation}

Para uma amostra em Flexão em três pontos, um resultado da Mecânica Aplicada indica que: \begin{equation} \frac{\sigma(y)}{\sigma_{max}} = \frac{4 \ x \ y}{L \ h} \end{equation}

test

Figura 11: Geometria do Ensaio de Flexão 3 Pontos.

Assim, considerando que o volume da amostra solicitado (isto é, o volume entre os apoios) é $V= b \ L \ h$:

\begin{equation} k_{3pt} = \frac{1}{V} \int_{0}^{L}\left(\frac{2 x}{L}\right)^{m} d x \int_{0}^{h / 2}\left(\frac{2 y}{h}\right)^{m} d y \int_{0}^{b} d z= \frac{L \ h \ b}{V \ 2 \ (m+1)^{2}} = \frac{1}{2(m+1)^{2}} \end{equation}

Adotando uma estratégia similar àquela utilizada para a análise do efeito do volume, igualando as probabilidade de falha para um ensaio em tração uniaxial e em flexão três pontos chegamos em:

\begin{equation} \frac{\sigma_{f, 3 pt}}{\sigma_{f, t}}=\left(\frac{k_{t}}{k_{3 pt}}\right)^{1 / m}=\left[2(m+1)^{2}\right]^{1 / m} \end{equation}

Usando esta metodologia analítica para o ensaio de quatro pontos resulta em: \begin{equation} \frac{\sigma_{f, 4 pt}}{\sigma_{f, t}}=\left(\frac{k_{t}}{k_{4 pt}}\right)^{1 / m}=\left[\frac{4(m+1)^{2}}{m+2}\right]^{1 / m} \end{equation}

Esses comportamentos podem ser visualizados a seguir:

# HIDDEN

ms = np.linspace(1, 500, 10000)
fig = plt.figure(figsize=(8, 6))
three_t =  lambda m: (2*(m+1)**2)**(1/m)
four_t = lambda m: (4*(m+1)**2/(m+2))**(1/m)
plt.plot(ms, three_t(ms), lw=3, label=r'$\frac{\sigma_{f, 3pt}}{\sigma_{f,t}}$', c='navy')
plt.plot(ms, four_t(ms), lw=3, label=r'$\frac{\sigma_{f, 4pt}}{\sigma_{f,t}}$', c='orangered')
plt.ylabel(r'$\frac{\sigma_{f, b}}{\sigma_{f, t}}$')
plt.xlabel(r'$m$')

plt.gca().set_xscale('log')
plt.grid()
plt.legend()
plt.show()
Figura 12: Efeito do Módulo de Weibull na tensão de falha em diferentes ensaios..

Como Obter os Parâmetros de Weibull?

Uma forma é através do Gráfico de Weibull. Ele é uma linearização da probabilidade de falha (como a teoria de cristalização de Avrami ou a lei de potências de um fluído não-newtoniano).

Para tanto, utiliza-se a aplicação da função log duplamente (uma vez para reduzir a exponenciação e uma segunda para a potência $m$):

\begin{equation} \ln \ln \left(\frac{1}{1-P_{f}}\right) = m \ln\left( \frac{\sigma}{\sigma_{0}}\right) \end{equation}
#@title
# HIDDEN

weibull_pdf = lambda sigma, m, sigma_0: np.exp(-(sigma/sigma_0)**m)
sigma_0 = 20e6
sigmas_f_m5 = np.sort(np.random.weibull(5, 60)*sigma_0)
sigmas_f_m15 = np.sort(np.random.weibull(15, 60)*sigma_0)

S_m5 = weibull_pdf(sigmas_f_m5, 5, sigma_0)
S_m15 = weibull_pdf(sigmas_f_m15, 15, sigma_0)

fig, axs = plt.subplots(1, 2, figsize=(16, 6))

axs[0].plot(sigmas_f_m5*1e-6, S_m5, '-o', c='navy', label='m = 5')
axs[0].plot(sigmas_f_m15*1e-6, S_m15, '-o', c='coral', label='m = 15')

axs[0].axhline(0, c='k', zorder=0, lw=1)
axs[0].axvline(0, c='k', zorder=0, lw=1)
axs[0].set_ylabel(r'$P_S$', fontsize=15)
axs[0].set_xlabel(r'$\frac{\sigma}{\sigma_0}$', fontsize=15)



axs[1].scatter(np.log(sigmas_f_m5 / sigma_0), np.log(np.log(1 / S_m5)), c='navy', label='m = 5')
axs[1].scatter(np.log(sigmas_f_m15 / sigma_0), np.log(np.log(1 / S_m15)), c='coral', label='m = 15')

axs[1].axhline(0, c='k', zorder=0, lw=1)
axs[1].axvline(0, c='k', zorder=0, lw=1)
axs[1].set_ylabel(r'$\ln{\ln{\ \frac{1}{P_S}}}$', fontsize=15)
axs[1].set_xlabel(r'$\ln{\ \frac{\sigma}{\sigma_0}}$', fontsize=15)

for ax in axs:
    for side in ['top','right','bottom','left']:
        ax.spines[side].set_visible(False)
    ax.tick_params(axis='both',which='both',labelbottom=True,bottom=False,left=False)
    ax.legend(fontsize=15)

axs[0].set_xlim(0, 30)
plt.tight_layout(w_pad=2)
plt.show()

Figura 13: Gráfico de Weibull para obtenção dos parâmetros de Weibull.

Como queremos obter o módulo de Weibull a partir de uma interpolação linear, podemos tirar proveito da propriedade de divisão do argumento da função $\log$ para separar o coeficiente angular ($a$) e o coeficiente linear ($b$) da reta a ser interpolada:

\begin{equation} \underbrace{\ln \ln \left(\frac{1}{1-P_{f}}\right)}_{f(x)} = \underbrace{m}_a \underbrace{\ln\left({\sigma}\right)}_x - \underbrace{m \ln\left({\sigma_0}\right)}_{b} \end{equation}

E assim podemos encontrar o módulo de Weibull, $m$ bem como o parâmetro $\sigma_0$ da seguinte maneira:

\begin{equation} m = a \\ \sigma_0 = \exp{\left(\frac{b}{a}\right)} \end{equation}
#@title 
# HIDDEN

def weibull_view_2(m_1, sigma_1):
    weibull_cdf = lambda sigma, m, sigma_0: np.exp(-(sigma/sigma_0)**m)
    sigma_0 = 20e6
    sigmas_f_m5 = np.sort(np.random.weibull(5, 60)*sigma_0)
    sigmas_f_m15 = np.sort(np.random.weibull(m_1, 60)*sigma_1*1e6)

    S_m5 = weibull_cdf(sigmas_f_m5, 5, sigma_0)
    S_m15 = weibull_cdf(sigmas_f_m15, m_1, sigma_1*1e6)

    fig, axs = plt.subplots(1, 2, figsize=(8, 4.5))

    axs[0].plot(sigmas_f_m5*1e-6, S_m5, '-o', c='navy', label='$\sigma_0$ = 20MPa, m = 5')
    axs[0].plot(sigmas_f_m15*1e-6, S_m15, '-o', c='coral', label=f'$\sigma_0$ = {round(sigma_1, 2)}MPa, m = {m_1}')

    axs[0].axhline(0, c='k', zorder=0, lw=1)
    axs[0].axvline(0, c='k', zorder=0, lw=1)
    axs[0].set_ylabel(r'$P_S$', fontsize=15)
    axs[0].set_xlabel(r'$\frac{\sigma}{\sigma_0}$', fontsize=15)



    axs[1].scatter(np.log(sigmas_f_m5 / sigma_0), np.log(np.log(1 / S_m5)), c='navy', label='$\sigma_0$ = 20MPa, m = 5')
    axs[1].scatter(np.log(sigmas_f_m15 / (sigma_1*1e6)), np.log(np.log(1 / S_m15)), c='coral', label=f'$\sigma_0$ = {round(sigma_1, 2)}MPa, m = {m_1}')

    axs[1].axhline(0, c='k', zorder=0, lw=1)
    axs[1].axvline(0, c='k', zorder=0, lw=1)
    axs[1].set_ylabel(r'$\ln{\ln{\ \frac{1}{P_S}}}$', fontsize=15)
    axs[1].set_xlabel(r'$\ln{\ \frac{\sigma}{\sigma_0}}$', fontsize=15)

    for ax in axs:
        for side in ['top','right','bottom','left']:
            ax.spines[side].set_visible(False)
        ax.tick_params(axis='both',which='both',labelbottom=True,bottom=False,left=False)
        ax.legend(loc='upper left', fontsize=10)

#     axs[0].set_xlim(0, 30)
    plt.tight_layout(w_pad=2)
    plt.show()

int_plot = interactive(weibull_view_2,
                       sigma_1=widgets.FloatSlider(value=5,
                                                       min=5,
                                                       max=45,
                                                       step=1,
                                                       description='$\sigma_0$ [MPa]',
                                                       readout_format='.2f'),
                       m_1=widgets.FloatSlider(value=2,
                                                       min=1,
                                                       max=80,
                                                       step=4,
                                                       description='$m$ [-]',
                                                       readout_format='.2f')
                      )
output = int_plot.children[-1]
output.layout.height = '580px'
int_plot.layout = widgets.Layout(display='flex',
                               flex_flow='column-reverse',
                               align_items='center',
                               align_content='center',
                               justify_content='center',
                               width='100%')
int_plot

Widget 5: Visualização dos parâmetros no gráfico de Weibull.
#@title
# HIDDEN

def weibull_view_3(m_1, sigma_1):
    weibull_cdf = lambda sigma, m, sigma_0: np.exp(-(sigma/sigma_0)**m)
    sigma_0 = 20e6
    sigmas_f_m5 = np.sort(np.random.weibull(5, 60)*sigma_0)
    sigmas_f_m15 = np.sort(np.random.weibull(m_1, 60)*sigma_1*1e6)

    S_m5 = weibull_cdf(sigmas_f_m5, 5, sigma_0)
    S_m15 = weibull_cdf(sigmas_f_m15, m_1, sigma_1*1e6)

    fig, axs = plt.subplots(1, 2, figsize=(8, 4.5))

    axs[0].plot(sigmas_f_m5*1e-6, S_m5, '-o', c='navy', label='$\sigma_0$ = 20MPa, m = 5')
    axs[0].plot(sigmas_f_m15*1e-6, S_m15, '-o', c='coral', label=f'$\sigma_0$ = {round(sigma_1, 2)}MPa, m = {m_1}')

    axs[0].axhline(0, c='k', zorder=0, lw=1)
    axs[0].axvline(0, c='k', zorder=0, lw=1)
    axs[0].set_ylabel(r'$P_S$', fontsize=15)
    axs[0].set_xlabel(r'$\frac{\sigma}{\sigma_0}$', fontsize=15)



    axs[1].scatter(np.log(sigmas_f_m5), np.log(np.log(1 / S_m5)), c='navy', label='$\sigma_0$ = 20MPa, m = 5')
    axs[1].scatter(np.log(sigmas_f_m15), np.log(np.log(1 / S_m15)), c='coral', label=f'$\sigma_0$ = {round(sigma_1, 2)}MPa, m = {m_1}')

    axs[1].axhline(0, c='k', zorder=0, lw=1)
    axs[1].axvline(0, c='k', zorder=0, lw=1)
    axs[1].set_ylabel(r'$\ln{\ln{\ \frac{1}{P_S}}}$', fontsize=15)
    axs[1].set_xlabel(r'$\ln{\sigma}$', fontsize=15)

    for ax in axs:
        for side in ['top','right','bottom','left']:
            ax.spines[side].set_visible(False)
        ax.tick_params(axis='both',which='both',labelbottom=True,bottom=False,left=False)
        ax.legend(loc='upper left', fontsize=10)

    axs[1].set_xlim(10, 20)
    plt.tight_layout(w_pad=2)
    plt.show()

int_plot = interactive(weibull_view_3,
                       sigma_1=widgets.FloatSlider(value=5,
                                                       min=5,
                                                       max=45,
                                                       step=1,
                                                       description='$\sigma_0$ [MPa]',
                                                       readout_format='.2f'),
                       m_1=widgets.FloatSlider(value=5,
                                                       min=1,
                                                       max=80,
                                                       step=4,
                                                       description='$m$ [-]',
                                                       readout_format='.2f')
                      )
output = int_plot.children[-1]
output.layout.height = '580px'
int_plot.layout = widgets.Layout(display='flex',
                               flex_flow='column-reverse',
                               align_items='center',
                               align_content='center',
                               justify_content='center',
                               width='100%')
int_plot

Widget 6: Visualização dos parâmetros no gráfico de Weibull adaptado.

Entretanto, para este plot é necessário obter a probabilidade de sobrevivência cada corpo. Vejamos como obter tal quantia. Considere um ensaio com um número n de amostras a partir do qual será obtido o módulo de Weibull. Iniciamos listando os dados brutos em uma tabela e em seguida ordenamos do menor para o maior, ranqueando os dados:

# HIDDEN
# nbi:left
pd.set_option('display.max_rows', None)
sigma_0 = 20e6
weibull_m5 = stats.weibull_min(5, 0, sigma_0)
N=60
sigmas_f_m5 = weibull_m5.rvs(size=N)
# sigmas_f_m5 = pd.read_clipboard(header=None).values.flatten()
df_1 = pd.DataFrame([sigmas_f_m5*1e-6]).T
df_1.columns = ['$\sigma_f$ [MPa]']
df_1.index.name = 'Amostra'
print('Dados Brutos:')
df_1.round(decimals=2)
Dados Brutos:
Amostra $\sigma_f$ [MPa]
0 19.58
1 19.48
2 25.33
3 22.69
4 17.92
5 21.53
6 21.29
7 25.42
8 17.10
9 9.36
10 19.48
11 15.50
12 23.76
13 20.26
14 21.97
15 28.55
16 18.71
17 16.02
18 22.72
19 16.21
20 22.95
21 9.99
22 19.11
23 15.59
24 19.48
25 24.30
26 19.03
27 20.28
28 20.95
29 16.46
30 20.48
31 22.12
32 23.37
33 21.92
34 17.20
35 17.54
36 13.36
37 24.88
38 17.47
39 23.75
40 16.04
41 15.51
42 18.33
43 19.66
44 19.13
45 19.05
46 10.79
47 12.91
48 20.43
49 19.53
50 15.17
51 20.40
52 18.25
53 21.30
54 11.19
55 15.41
56 20.29
57 22.58
58 12.56
59 13.22
# HIDDEN
# nbi:right
print('Dados Ordenados:')
df_1 = df_1.sort_values('$\sigma_f$ [MPa]')
df_1['Rank, i'] = np.arange(1, N+1)
df_1.round(decimals=2)
Dados Ordenados:
Amostra $\sigma_f$ [MPa] Rank, i
9 9.36 1
21 9.99 2
46 10.79 3
54 11.19 4
58 12.56 5
47 12.91 6
59 13.22 7
36 13.36 8
50 15.17 9
55 15.41 10
11 15.50 11
41 15.51 12
23 15.59 13
17 16.02 14
40 16.04 15
19 16.21 16
29 16.46 17
8 17.10 18
34 17.20 19
38 17.47 20
35 17.54 21
4 17.92 22
52 18.25 23
42 18.33 24
16 18.71 25
26 19.03 26
45 19.05 27
22 19.11 28
44 19.13 29
10 19.48 30
24 19.48 31
1 19.48 32
49 19.53 33
0 19.58 34
43 19.66 35
13 20.26 36
27 20.28 37
56 20.29 38
51 20.40 39
48 20.43 40
30 20.48 41
28 20.95 42
6 21.29 43
53 21.30 44
5 21.53 45
33 21.92 46
14 21.97 47
31 22.12 48
57 22.58 49
3 22.69 50
18 22.72 51
20 22.95 52
32 23.37 53
39 23.75 54
12 23.76 55
25 24.30 56
37 24.88 57
2 25.33 58
7 25.42 59
15 28.55 60

Assim é possível estimar $P_f$ a partir do rank $i$ seguindo a Equação abaixo:

\begin{equation} P_f(i) = \frac{i-0.3}{n+0.4} \end{equation}

Note que é a partir desta etapa em que podemos categoricamente afirmar qual é a probabilidade do material falhar para um dado estado e valor de tensão, conforme ilustrado no Widget a seguir:

# HIDDEN
m_1 = 15
sigma_1 = 20
weibull_cdf = lambda sigma, m, sigma_0: np.exp(-(sigma/sigma_0)**m)
sigma_0 = 20e6
sigmas_f_m5 = np.sort(np.random.weibull(5, 100)*sigma_0)
sigmas_f_m15 = np.sort(np.random.weibull(15, 100)*sigma_1*1e6)
def weibull_view_2(percent):
    S_m5 = 1-weibull_cdf(sigmas_f_m5, 5, sigma_0)
    S_m15 = 1-weibull_cdf(sigmas_f_m15, 15, sigma_1*1e6)

    fig, axs = plt.subplots(1, 1, figsize=(14*0.85, 8*0.85))

    axs.plot(sigmas_f_m5*1e-6, S_m5 * 100, '-o', c='navy',
             label='$\sigma_0$ = 20MPa, m = 5')
    axs.plot(sigmas_f_m15*1e-6, S_m15 * 100, '-o', c='coral',
             label=f'$\sigma_0$ = {round(sigma_1, 2)}MPa, m = {15}')

    sig_percent_m5 = np.interp(percent, S_m5[::1] * 100, sigmas_f_m5[::1])
    sig_percent_m15 = np.interp(percent, S_m15[::1] * 100, sigmas_f_m15[::1])
    
    axs.plot(sig_percent_m5 * 1e-6, percent, 'o',
             markerfacecolor='w', markersize=12, markeredgewidth=4, c='gold', zorder=150)
    axs.plot(sig_percent_m15 * 1e-6, percent, 'o',
             markerfacecolor='w', markersize=12, markeredgewidth=4, c='gold', zorder=150)
    axs.axvline(sig_percent_m5 * 1e-6, lw=2, color='navy')
    axs.axvline(sig_percent_m15 * 1e-6, lw=2, color='coral')
    
    axs.axhline(0, c='k', zorder=0, lw=1)
    axs.axvline(0, c='k', zorder=0, lw=1)
    axs.set_ylabel(r'$P_f$ [%]', fontsize=20)
    axs.set_xlabel(r'$\sigma$ [MPa]', fontsize=20)
    axs.axhline(percent, 0.03, color='k', lw=2, ls='-')
    axs.set_xlim(-1.5, 30)
    axs.set_ylim(-5, 102.5)
    
    
    bb = mpl.transforms.Bbox([[2, 13.5], [10, 50]])
    fancy = mpl.patches.FancyBboxPatch(bb.p0, bb.width, bb.height,
                           fc='w', ec='0.8', alpha=0.8, zorder=100)
    axs.add_patch(fancy)
    axs.text(6, 32, f'Probabilidade de\nFalha:\n$P_f$ = {round(percent, 2)}%',
             horizontalalignment='center', zorder=100, fontsize=20)
    
    for i in range(3):
        axs.text(6.1, 24, f'$\sigma_f$ = {round(sig_percent_m5 * 1e-6, 2)} MPa',
                 horizontalalignment='center', zorder=100, color='navy', fontsize=20)
        axs.text(6.1, 16, f'$\sigma_f$ = {round(sig_percent_m15 * 1e-6, 2)} MPa',
                 horizontalalignment='center', zorder=100, color='coral', fontsize=20)

    for ax in [axs]:
        for side in ['top','right','bottom','left']:
            ax.spines[side].set_visible(False)
        ax.tick_params(axis='both', which='both', labelbottom=True, bottom=False, left=False)
    axs.legend(loc='upper left', bbox_to_anchor=(0.0907, 0.7), fontsize=16)
    plt.tight_layout(w_pad=2)
    plt.show()

int_plot = interactive(weibull_view_2,
                       percent=widgets.FloatSlider(value=50,
                                                       min=0,
                                                       max=100,
                                                       step=5,
                                                       description='$P_f$',
                                                       readout_format='.2f')
                      )
output = int_plot.children[-1]
output.layout.height = '550px'
int_plot.layout = widgets.Layout(display='flex',
                               flex_flow='column-reverse',
                               align_items='center',
                               align_content='center',
                               justify_content='center',
                               width='100%')
int_plot
Widget 7: Probabilidade de Falha de dois materiais com módulos de Weibull diferentes.

Observe também como o módulo de Weibull afeta o valor da tensão máxima (isto é, a tensão para $P_f$ = 100%) suportada para materiais de mesmo valor de $\sigma_0$: a maior dispersão do material com menor módulo resulta em maiores valores de tensão máxima. Esse "melhor desempenho", porém, é acompanhado de uma maior dispersão dos resultados, o que também afeta negativamente o valor de tensão que garanta máxima sobrevivência do material (por exemplo quando $P_S$ = 100% - $P_f$ = 99%)

Uma vez obtida a probabilidade de falha é possível realizar a linearização do gráfico conforme ilustrado a seguir:

# HIDDEN

df_1['P_s'] = 1 - (df_1['Rank, i']-0.3)/(N+0.4)
df_1[r'lnln($\frac{1}{P_s}$)'] = np.log(np.log(1/df_1['P_s']))
df_1[r'ln($\sigma_f$)'] = np.log(df_1['$\sigma_f$ [MPa]'])
df_1_r = df_1.round(decimals=2)
df_1_r['P_s'] = df_1['P_s'].round(decimals=3)
df_1_r
Amostra $\sigma_f$ [MPa] Rank, i P_s lnln($\frac{1}{P_s}$) ln($\sigma_f$)
9 9.36 1 0.988 -4.45 2.24
21 9.99 2 0.972 -3.56 2.30
46 10.79 3 0.955 -3.08 2.38
54 11.19 4 0.939 -2.76 2.42
58 12.56 5 0.922 -2.51 2.53
47 12.91 6 0.906 -2.31 2.56
59 13.22 7 0.889 -2.14 2.58
36 13.36 8 0.873 -1.99 2.59
50 15.17 9 0.856 -1.86 2.72
55 15.41 10 0.839 -1.74 2.73
11 15.50 11 0.823 -1.63 2.74
41 15.51 12 0.806 -1.54 2.74
23 15.59 13 0.790 -1.44 2.75
17 16.02 14 0.773 -1.36 2.77
40 16.04 15 0.757 -1.28 2.77
19 16.21 16 0.740 -1.20 2.79
29 16.46 17 0.724 -1.13 2.80
8 17.10 18 0.707 -1.06 2.84
34 17.20 19 0.690 -0.99 2.84
38 17.47 20 0.674 -0.93 2.86
35 17.54 21 0.657 -0.87 2.86
4 17.92 22 0.641 -0.81 2.89
52 18.25 23 0.624 -0.75 2.90
42 18.33 24 0.608 -0.70 2.91
16 18.71 25 0.591 -0.64 2.93
26 19.03 26 0.575 -0.59 2.95
45 19.05 27 0.558 -0.54 2.95
22 19.11 28 0.541 -0.49 2.95
44 19.13 29 0.525 -0.44 2.95
10 19.48 30 0.508 -0.39 2.97
24 19.48 31 0.492 -0.34 2.97
1 19.48 32 0.475 -0.30 2.97
49 19.53 33 0.459 -0.25 2.97
0 19.58 34 0.442 -0.20 2.97
43 19.66 35 0.425 -0.16 2.98
13 20.26 36 0.409 -0.11 3.01
27 20.28 37 0.392 -0.07 3.01
56 20.29 38 0.376 -0.02 3.01
51 20.40 39 0.359 0.02 3.02
48 20.43 40 0.343 0.07 3.02
30 20.48 41 0.326 0.11 3.02
28 20.95 42 0.310 0.16 3.04
6 21.29 43 0.293 0.20 3.06
53 21.30 44 0.276 0.25 3.06
5 21.53 45 0.260 0.30 3.07
33 21.92 46 0.243 0.35 3.09
14 21.97 47 0.227 0.39 3.09
31 22.12 48 0.210 0.44 3.10
57 22.58 49 0.194 0.50 3.12
3 22.69 50 0.177 0.55 3.12
18 22.72 51 0.161 0.60 3.12
20 22.95 52 0.144 0.66 3.13
32 23.37 53 0.127 0.72 3.15
39 23.75 54 0.111 0.79 3.17
12 23.76 55 0.094 0.86 3.17
25 24.30 56 0.078 0.94 3.19
37 24.88 57 0.061 1.03 3.21
2 25.33 58 0.045 1.13 3.23
7 25.42 59 0.028 1.27 3.24
15 28.55 60 0.012 1.49 3.35
# HIDDEN
def r_squared(y, y_hat):
    y_bar = y.mean()
    ss_tot = ((y-y_bar)**2).sum()
    ss_res = ((y-y_hat)**2).sum()
    return 1 - (ss_res/ss_tot)

plt.figure(figsize=(7, 7))
plt.plot(df_1[r'ln($\sigma_f$)'], df_1[r'lnln($\frac{1}{P_s}$)'], 'o', label='Dados Experimentais', c='navy', lw=3)
m_interp, sig_0_interp = np.polyfit(df_1[r'ln($\sigma_f$)'], df_1[r'lnln($\frac{1}{P_s}$)'], 1)
plt.plot(df_1[r'ln($\sigma_f$)'], df_1[r'ln($\sigma_f$)']*m_interp+sig_0_interp, '-', label='Interpolação', c='orangered', lw=3)
sigs = np.linspace(1e6, 40e6, 1000)
# plt.plot(np.log(sigs*1e-6), np.log(np.log(1/(1-weibull_m5.cdf(sigs)))), '-k', label='Resultado Analítico', lw=3)
plt.text(2.8, -1.95, '$m_{exp}$ = ' + str(round(m_interp, 2)))
plt.text(2.8, -2.3, '$\sigma_{0, exp}$ = ' + str(round(np.exp(-sig_0_interp/m_interp), 2)) + ' MPa')
plt.text(2.8, -1.6, '$r^2$ = ' + str(round(r_squared(df_1[r'lnln($\frac{1}{P_s}$)'], df_1[r'ln($\sigma_f$)']*m_interp+sig_0_interp), 2)))

plt.ylabel(r'$\log{\log{\ \frac{1}{P_S}}}$', fontsize=15)
plt.xlabel(r'$\log{\ \sigma}$', fontsize=15)

plt.xlim(2.25, 3.5)
plt.ylim(-5, 4)
plt.legend(fontsize=16)
plt.grid()
plt.show()
Figura 14: Exemplo de obtenção do módulo de Weibull usando uma regressão linear.

Alguns Comentários Sobre o Módulo de Weibull:

  • Qual o número de corpos de prova que compõe uma amostra para se estimar o módulo de Weibull?

O gráfico a seguir ilustra como o erro na obtenção do módulo de Weibull diminui com o aumento do número de amostras consideradas:

# HIDDEN

plt.figure(figsize=(10, 5.5))
Ns = np.linspace(1, 100, 1000)
m_1 = 1
m_5 = 5

plt.plot(Ns, 1 / (2*Ns)**0.5*100, c='navy', lw=2)
plt.text(20, 50, r'Módulo de Weibull = $m \pm \dfrac{m}{\sqrt{2 \ N}}$')
plt.text(99, 10, str(int((1 / (2*Ns)**0.5*100)[-1]))+'%')
plt.grid()
plt.ylabel('$e$ [%]')
plt.xlabel('Número de corpos de prova')
plt.show()
Figura 15: Erro na estimativa do Módulo de Weibull em função do número de corpos de prova.

Note que a partir de 100 amostras o erro cai para 7%, enquanto o uso de 50 amostras leva a um erro de 10%. Estas estimativas teóricas também são confirmadas experimentalmente conforme o trabalho de Glandus et al.

test

Figura 16: Glandus et al., Uncertainty on the mean strength and Weibull's modulus of an alumina batch as a function of the number of samples. Efeito do tamanho da amostra na obtenção do módulo de Weibull e da tensão de fratura média.

  • O módulo de Weibull não está relacionado apenas ao material, mas é influenciado também pela repetibilidade dos CPs
  • É necessário se atentar que o comportamento da amostra (de seguir uma distribuição de probabilidade de falha igual ao de Weibull) foi ASSUMIDO como sendo o comportamento real. Este caráter fenomenológico é uma das principais críticas à analise de Weibull

Qual Material Possui Maior $m$?

# HIDDEN

fig, axs = plt.subplots(3, 3, figsize=(20, 4))
for ax in axs.flatten():
    ax.tick_params(left=False,
                bottom=False,
                labelleft=False,
                labelbottom=False)
axs[0, 0].set_title('Material A', fontsize=16)
axs[0, 1].set_title('Material B', fontsize=16)
axs[0, 2].set_title('Material C', fontsize=16)

for i in range(7):
    axs[0,0].scatter(np.random.normal(), np.random.normal(), marker='$/$', s=200, c='k')
    axs[1,0].scatter(np.random.normal(), np.random.normal(), marker='$/$', s=200, c='k')
    axs[2,0].scatter(np.random.normal(), np.random.normal(), marker='$/$', s=200, c='k')

for i in range(10):
    axs[0,1].scatter(np.random.normal(), np.random.normal(), marker='$/$', s=200, c='k')
for i in range(5):
    axs[1,1].scatter(np.random.normal(), np.random.normal(), marker='$/$', s=200, c='k')
for i in range(30):
    axs[2,1].scatter(np.random.normal(), np.random.normal(), marker='$/$', s=200, c='k')
    
    
for i in range(5):
    axs[0,2].scatter(np.random.normal(), np.random.normal(), marker='$/$', s=200, c='k')
for i in range(2):
    axs[2,2].scatter(np.random.normal(), np.random.normal(), marker='$/$', s=200, c='k')
    
plt.show()

O Material A é aquele cuja dispersão de defeitos é a mais homogênea tanto em quantidade quanto em distribuição espacial.

Logo, é aquele de maior reprodutibilidade, e assim, maior módulo de Weibull.

Observações Experimentais

Valores comuns de módulo de Weibull


Materiais Cerâmicos Materiais Metálicos* Materiais Poliméricos*
5<m<15 100<m<500 50<m<150

Exemplo da influência do processamento no módulo de Weibull


Concreto com Cimento Portland Concreto com Cimento Portland + Dispersante
m=3,5 m=20

O concreto (seja ele de construção civil ou refratário) é um material composto por diferentes fases destribuídas em sua microestrutura em diversas escalas de tamanho, como revelado pela tomografia de raios-X apresentada abaixo:

Microstrutura de um Concreto Refratário
Figura 17: Microestrutura de um Concreto Refratário a partir de tomografia de raios-X.

É possível visualizar poros, agregados e a matriz. Adicionalmente, em escalas menores, dentro da própria matriz seria possível encontrar microporos, agregados finos e fases hidratadas do cimento, ou ainda particulados que não reagiram com a água adicionada. Nos poros, também identifica-se filmes líquidos de água que não foi consumida durante sua cura. Assim, dada sua complexidade e heterogeneidade, medidas que promovam uma distribuição mais homogenêa destas fases em todo seu volume, como o uso de dispersantes, garantem uma maior reprodutibilidade e, assim, um maior módulo de Weibull.

O que acontece com o m quando uma amostra a verde é queimada?

O trabalho de Kendall et al. demonstra que a queima de corpos a verde não altera significativamente o módulo de Weibull, embora o $K_{IC}$ do material tenha sido ampliado mais de sete vezes. Esse resultado é de extrema importância pois além de demonstrar que processos que atuem de forma homogênea no material (como uma queima realizada em um forno com baixo gradiente térmico) não são capazes de alterar a distribuição dos defeitos nos materiais, ilustram que não há nenhuma relação entre o módulo de Weibull, $m$, e a tenacidade a fratura dos materiais, $K_{IC}$.

test

Figura 18: Kendall et al., Influence ot Toughness on Weibull modulus of Ceramics. Efeito da queima no módulo de Weibull.

Materiais de maior tenacidade à fratura possuem a fama de ser mais confiáveis. Por quê?

Efeito dos danos ao longo do tempo de vida do material alteram o módulo de Weibull, especialmente para aqueles materiais onde tais danos ocorrem de maneira mais fácil (menor tenacidade).

Considerações Finais

  • O comportamento mecânico dos materiais é sucetível a diversas fontes de variabilidade (até mesmo erros de medida!)
  • Representações matemáticas podem descrever este comportamento (médias, desvios, distribuições estatísticas)
  • A probabilidade de falha de um material pode ser descrita por tais distribuições
  • Em sua derivação, conceitos clássicos como a teoria do elo mais fraco geraram insights de grande importância como o efeito do volume e do ensaio
  • O módulo de Weibull descreve a variabilidade de um determinado conjunto de amostras e serve para:
    • Poder comparar materiais distintos e obtidos por processamentos diferentes
    • Converter resultados entre corpos de prova de diferentes dimensões e de ensaios distintos

Visualização Prática do Módulo de Weibull

O Widget abaixo apresenta todas as etapas do processo de obtenção do Módulo de Weibull. Tente explorar os parâmetros (mova os sliders para os resultados aparecerem)!

Esta análise pode ser realizada em ensaios de flexão 3 ou 4 pontos com amostras prismáticas considerando uma aplicação final para uma barra sob tração.

Lembre-se das equações de conversão:

$$\sigma_{f, t} = \left[2(m+1)^{2}\right]^{-\frac{1}{m}} \ \sigma_{f, 3 pt}$$$$\sigma_{f, t} = \left[\frac{4(m+1)^{2}}{m+2}\right]^{-\frac{1}{m}} \ \sigma_{f, 4 pt}$$\begin{equation} \frac{\sigma_{a}}{\sigma_{b}}=\left(\frac{V_{b}}{V_{a}}\right)^{\frac{1}{m}} \end{equation}
# HIDDEN
import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning) 
pd.set_option('display.max_rows', 10)
# Wayne Nelson (2004) Applied Life Data Analysis
# ASTM Pf = (i-0.5) / N
np.random.seed(seed=233423)
estimador = 'Wayne'
def weibull_experiment(N, m, sigma_0):
    global weibull_m
    weibull_m = stats.weibull_min(m, 0, sigma_0)
    global sigmas_f_m
    sigmas_f_m = weibull_m.rvs(size=int(N), random_state=233423)
    global df_1
    df_1 = pd.DataFrame([sigmas_f_m]).T
    df_1.columns = ['σ_f [MPa]']
    df_1.index.name = 'Amostra'
    df_1 = df_1.sort_values('σ_f [MPa]')
    df_1['Rank, i'] = np.arange(1, N+1)
    if estimador=='Wayne':
        df_1['P_s'] = 1 - (df_1['Rank, i']-0.3)/(N+0.4)
    elif estimador=='ASTM':
        df_1['P_s'] = 1 - (df_1['Rank, i']-0.5)/(N)
            
    df_1[r'lnln(1/Ps)'] = np.log(np.log(1/df_1['P_s']))
    df_1[r'ln(σ_f)'] = np.log(df_1['σ_f [MPa]'])
    df_1 = df_1.round(decimals=2)
    display(df_1)
    
def weibull_plot(N, m, sigma_0):
    global weibull_m 
    global sigmas_f_m 
    global df_1
    with np.errstate(divide='ignore'):

        fig = plt.figure(figsize=(6, 6))
        plt.plot(df_1[r'ln(σ_f)'], df_1[r'lnln(1/Ps)'], 'o', label='Dados Experimentais', c='navy', lw=3)
        x = df_1[r'ln(σ_f)']
        y = df_1[r'lnln(1/Ps)']
        m_interp, sig_0_interp = np.polyfit(x, y, 1)
        r_squared = 1 - (sum((y - (m_interp * x + sig_0_interp))**2) / ((len(y) - 1) * np.var(y, ddof=1)))
        plt.plot(df_1[r'ln(σ_f)'], df_1[r'ln(σ_f)']*m_interp+sig_0_interp, '-', label='Interpolação', c='orangered', lw=3)
        sigs = np.logspace(0, 6, 1000)
        plt.plot(np.log(sigs), np.log(np.log(1/(1-weibull_m.cdf(sigs)))), '-k', label='Resultado Analítico', lw=3)
    plt.text(0.1, 4.3, '$m_{exp}$ = ' + str(round(m_interp, 2)), fontsize=13)
    plt.text(0.1, 3.6, '$\sigma_{0, exp}$ = ' + str(round(np.exp(-sig_0_interp/m_interp), 2)) + ' MPa', fontsize=13)
    plt.text(0.1, 2.6, '$r^2$ = ' + str(round(r_squared, 2)), fontsize=13)
    plt.ylabel(r'$\log{\log{\ \frac{1}{P_S}}}$', fontsize=15)
    plt.xlabel(r'$\log{\sigma}$', fontsize=15)
    plt.xticks(fontsize=16)
    plt.yticks(fontsize=16)

    plt.xlim(0, 6)
    plt.ylim(-10, 5)
    plt.legend(loc='lower right', fontsize=12)
    plt.grid()
    plt.show()
# select_est = widgets.Select(options=['Wayne', 'ASTM'])
slider_m = widgets.FloatSlider(value=5,
                                   min=1,
                                   max=100,
                                   step=1,
                                   description='$m$',
                                   orientation='horizontal')

slider_sig_0 = widgets.FloatSlider(value=20,
                                   min=2,
                                   max=100,
                                   step=5,
                                   description='$\sigma_0$',
                                   orientation='horizontal')

slider_N = widgets.FloatSlider(value=60,
                                   min=5,
                                   max=1000,
                                   step=5,
                                   description='# CP\'s, $N$',
                                   orientation='horizontal')
pd_show_int = interactive(weibull_experiment, N=slider_N, m=slider_m, sigma_0=slider_sig_0)
weibull_plot_show_int = interactive(weibull_plot, N=slider_N, m=slider_m, sigma_0=slider_sig_0)

eqs_header = widgets.HTML(r'<p>Equação de Weibull:</p>')
equations_weib = widgets.HTMLMath(r'$\ln \ln \left(\frac{1}{1-P_{f}}\right) = m \ln\left( \frac{\sigma}{\sigma_{0}}\right)$')
eqs_prob = widgets.HTMLMath(r'$P_f(i) = \frac{i-0.3}{n+0.4}$')
eqs = widgets.VBox([eqs_header, equations_weib, eqs_prob])
# eqs.layout = widgets.Layout(display='flex',
#                                flex_flow='column',
#                                align_items='center',
#                                align_content='center')
controls = widgets.HBox([widgets.VBox(pd_show_int.children[:3]), eqs])
pd_out = pd_show_int.children[-1]

#HIDDEN

three_t =  lambda m: (2*(m+1)**2)**(1/m)
four_t = lambda m: (4*(m+1)**2/(m+2))**(1/m)
space = widgets.HTMLMath('&emsp;&emsp;&emsp;')

def vol_ensaios(m, X_pec, Y_pec, Z_pec, X_am, Y_am, Z_am, ensaio, N, sigma_0):
    global sigmas_f_m
    mean_sig = np.mean(sigmas_f_m)
    V_amostra = X_am * 1e-3 * Y_am * 1e-3 * Z_am * 1e-3
    V_peca = X_pec * Y_pec * Z_pec
    if ensaio == 'Flexão 3 Pontos':
#         disp_mean_sig = widgets.HTMLMath(f'σ_(f, 3pt, amostra): {round(mean_sig, 2)} MPa')
        mean_sig_trac = mean_sig *  (2*(m+1)**2)**(-1/m)
#         disp_mean_sig_trac = widgets.HTMLMath(f'σ_(f, t, amostra): {round(mean_sig_trac, 2)} MPa')


    elif ensaio == 'Flexão 4 Pontos':
#         disp_mean_sig = widgets.HTMLMath(f'σ_(f, 4pt, amostra): {round(mean_sig, 2)} MPa')
        mean_sig_trac = mean_sig *  (4*(m+1)**2/(m+2))**(-1/m)
#         disp_mean_sig_trac = widgets.HTMLMath(f'σ_(f, t, amostra): {round(mean_sig_trac, 2)} MPa')
    mean_sig_peca = (V_amostra/V_peca)**(1/m) * mean_sig_trac
    disp_mean_sig_peca = widgets.HTMLMath(f'σ_(f, t, peça): {round(mean_sig_peca, 6)} MPa')
#     V_am = widgets.HTMLMath(f'Volume da CP: {round(V_amostra*1e6, 2)} cm³')
#     V_pec = widgets.HTMLMath(f'Volume da Peça: {round(V_peca, 2)} m³')
#     space_A = widgets.HTMLMath('&emsp;→&emsp;')
#     display(widgets.VBox([widgets.HBox([V_am, space, V_pec]), widgets.HBox([disp_mean_sig, space_A, disp_mean_sig_trac]), disp_mean_sig_peca]))
    print(f'Volume do CP: {round(V_amostra*1e6, 2)} cm³')
    print(f'Volume da Peça: {round(V_peca, 2)} m³')
    if ensaio == 'Flexão 3 Pontos':
        print(f'σ_(f, 3pt, amostra): {round(mean_sig, 2)} MPa')
        print(f'σ_(f, t, amostra): {round(mean_sig_trac, 2)} MPa')
    if ensaio == 'Flexão 4 Pontos':
        print(f'σ_(f, 4pt, amostra): {round(mean_sig, 2)} MPa')
        print(f'σ_(f, t, amostra): {round(mean_sig_trac, 2)} MPa')
    print(f'σ_(f, t, peça): {round(mean_sig_peca, 6)} MPa')


select_ensaio = widgets.Dropdown(description='Ensaio:', options=['Flexão 3 Pontos', 'Flexão 4 Pontos'])

    
slider_X_am = widgets.FloatSlider(value=125,
                                   min=5,
                                   max=1000,
                                   step=5,
                                   description='CP L [mm]:',
                                   orientation='horizontal')

slider_Y_am = widgets.FloatSlider(value=25,
                                   min=5,
                                   max=1000,
                                   step=5,
                                   description='CP H [mm]:',
                                   orientation='horizontal')

slider_Z_am = widgets.FloatSlider(value=25,
                                   min=5,
                                   max=1000,
                                   step=5,
                                   description='CP b [mm]:',
                                   orientation='horizontal')

slider_X_pec = widgets.FloatSlider(value=10,
                                   min=1,
                                   max=10,
                                   step=1,
                                   description='Peça L [m]:',
                                   orientation='horizontal')

slider_Y_pec = widgets.FloatSlider(value=1,
                                   min=1,
                                   max=10,
                                   step=1,
                                   description='Peça H [m]:',
                                   orientation='horizontal')

slider_Z_pec = widgets.FloatSlider(value=1,
                                   min=1,
                                   max=10,
                                   step=1,
                                   description='Peça b [m]:',
                                   orientation='horizontal')
weib_effects_int = interactive(vol_ensaios, m=slider_m, X_pec=slider_X_pec, Y_pec=slider_Y_pec, Z_pec=slider_Z_pec,
                               X_am=slider_X_am, Y_am=slider_Y_am, Z_am=slider_Z_am, ensaio=select_ensaio, N=slider_N, sigma_0=slider_sig_0)

weib_eff_controls = widgets.HBox([widgets.VBox(weib_effects_int.children[1:4]), widgets.VBox(weib_effects_int.children[4:7])])

aviso = widgets.HTMLMath('Observação: Altere o número de amostras, $N$, para plotar.')
weibull_output = widgets.VBox([aviso, controls, widgets.HBox([pd_out, weibull_plot_show_int.children[-1]]),
                              weib_eff_controls, weib_effects_int.children[7], weib_effects_int.children[10]])
weibull_output.layout = widgets.Layout(display='flex',
                               flex_flow='column',
                               align_items='center',
                               align_content='center')
out = widgets.Output()
with out:
    df_1

weibull_output
Widget 8: Visualização prática do Módulo de Weibull.

Muito obrigado!

Muito obrigado por sua participação e boa sorte com seus estudos! Para quaisquer dúvidas estaremos disponíveis nas monitorias (toda Terça-Feira 14:00 - 15:00).

Esta aula, bem como a lista, e o material de apoio fizeram uso de recursos de ensino pouco comuns como Widgets Interativos e um site de suporte.

Caso tenha 5 minutos, por favor, responda o formulário abaixo.

Grato, Murilo.