Skip to content

Commit 07124fe

Browse files
Commit versão 1.0
1 parent ecfabcc commit 07124fe

File tree

2 files changed

+208
-117
lines changed

2 files changed

+208
-117
lines changed

app.py

Lines changed: 18 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,30 @@
1+
from src.utils import reset_config, set_basic_info, set_sidebar_and_get_params, set_resultados
12
from src.calculadora import calcula_tensao_critica, calcular_abaco, calcular_v_max
2-
from src.utils import get_footer, set_chart, set_table
33
import streamlit as st
44

5-
st.set_page_config(
6-
page_title="Calculadora",
7-
page_icon=":coffee:",
8-
layout="wide",
9-
initial_sidebar_state="expanded"
10-
)
5+
reset_config(st)
116

12-
st.markdown(get_footer(), unsafe_allow_html=True)
7+
set_basic_info(st)
138

14-
st.title('Calculadora - Tensão Crítica')
15-
16-
st.markdown("""
17-
18-
Feito por: Marcelo Cardozo • [![GitHub](https://cdn.pixabay.com/photo/2022/01/30/13/33/github-6980894_1280.png)](https://github.com/marcelogcardozo)
19-
• [![LinkedIn](https://scontent.fsdu25-1.fna.fbcdn.net/v/t39.30808-1/267422938_4880673518668256_5792791296770782057_n.png?stp=dst-png_p200x200&_nc_cat=108&ccb=1-7&_nc_sid=754033&_nc_ohc=FzJ49MszpDkAX_b3T44&_nc_ht=scontent.fsdu25-1.fna&cb_e2o_trans=t&oh=00_AfC1YK5ssU0tc3BQcFnYLlPAJFN8jotV5pf9JJc-ANb7pQ&oe=650DDC2B)](https://www.linkedin.com/in/marcelogcardozo/)
20-
21-
Versão: 0.1.0
22-
""")
23-
24-
st.markdown(
25-
"""
26-
<style>
27-
img {
28-
width: 25px; /* Define a largura da imagem */
29-
height: 25px; /* Define a altura da imagem */
30-
border-radius: 50%; /* Cria um efeito de círculo */
31-
}
32-
</style>
33-
""",
34-
unsafe_allow_html=True,
35-
)
36-
37-
st.subheader('Resultados')
38-
st.divider()
39-
40-
# Parâmetros de entrada
41-
st.sidebar.title('Parâmetros de Entrada')
42-
43-
st.sidebar.subheader('Dados do Material')
44-
E = st.sidebar.number_input('Módulo de Elasticidade (GPa)', 0.1, None, 200.0) * 1000
45-
T_esc = st.sidebar.number_input('Tensão de Escoamento (MPa)', 0.1, None, 250.0)
46-
47-
st.sidebar.subheader('Dados da Seção Transversal')
48-
A = st.sidebar.number_input('Área (mm²)', 0.0, None, 0.0)
49-
I = st.sidebar.number_input('Inércia (mm⁴)', 0.0, None, 0.0)
50-
r = st.sidebar.number_input('Raio de Giração (mm)', 0.0, None, 0.0)
51-
c = st.sidebar.number_input('Distância da Linha Neutra (mm)', 0.0, None, 0.0)
52-
53-
st.sidebar.subheader('Dados do caso')
54-
P = st.sidebar.number_input('Carga aplicada (kN)', 0.0, None, 0.0)
55-
Le = st.sidebar.number_input('Comprimento efetivo do elemento (mm)', 0.1, None, 1000.0)
56-
e = st.sidebar.number_input('Excentricidade (mm)', 0.0, None, 0.0)
57-
FS = st.sidebar.number_input('Fator de Segurança', 0.0, None, 0.0)
58-
59-
gerar_abaco_completo = st.sidebar.checkbox('Gerar ábaco completo', value=False, key='gerar_abaco')
60-
61-
if gerar_abaco_completo:
62-
63-
de = st.sidebar.number_input('De', 0.0, 2.0, 0.0)
64-
ate = st.sidebar.number_input('Até', 0.1, 2.0, 1.0)
65-
66-
razao = st.sidebar.number_input('Razão', 0.1, 2.0, 0.1)
67-
else:
68-
de = 0.0
69-
ate = 1.0
70-
razao = 0.1
9+
E, T_esc, A, I, r, c, P, FS, Le, k, e, gerar_abaco_completo, de, ate, razao = set_sidebar_and_get_params(st)
7110

7211
# botao_calcular
7312
if st.sidebar.button('Calcular'):
7413

7514
with st.spinner('Calculando...'):
76-
77-
col1, col2, col3 = st.columns(3)
78-
col4, col5 = st.columns([0.85, 0.15])
79-
80-
if (I == 0 and r == 0):
81-
st.error('Inércia e Raio de Giração não podem ser ambos iguais a 0')
15+
16+
if A == 0:
17+
st.error('A área (A) não pode ser iguao a zero.')
18+
st.stop()
19+
elif (e > 0 and c == 0):
20+
st.error('A distância do centroide à fibra mais comprimida (c) não podem ser iguais a zero quando a excentricidade (e) for maior do que zero.')
21+
st.stop()
22+
elif (r == 0 and I == 0):
23+
st.error('O raio de giração (r) ou o momento de inércia (I) devem ser diferentes de zero.')
24+
st.stop()
25+
elif (Le == 0):
26+
st.error('O comprimento efetivo de flambagem (Le) não pode ser igual a zero.')
8227
st.stop()
83-
elif r == 0:
84-
r = (I / A) ** (1/2)
8528

8629
ecr2 = (e*c)/r**2
8730
Ler = Le/r
@@ -91,6 +34,7 @@
9134

9235
if (P == 0 and FS > 0):
9336
P = pcr / FS
37+
9438
tensao_normal_aplicada = (P * 1000) / A
9539

9640
v_max = calcular_v_max(P, pcr, e)
@@ -99,15 +43,5 @@
9943

10044
abaco = calcular_abaco(T_esc, ecr2, E, gerar_abaco_completo, de, ate, razao)
10145

102-
col1.latex('P_{cr} = '+f'{pcr:.2f} kN')
103-
col1.latex(f'P = {P:.2f} kN')
104-
105-
col2.latex('\sigma_{cr} = '+f'{tensao_normal_critica:.2f} MPa')
106-
col2.latex(f'\sigma = {tensao_normal_aplicada:.2f} MPa')
107-
col2.latex('V_{max} = '+f'{v_max:.2f} mm')
108-
109-
col3.latex(f'FS = {FS:.2f}')
110-
col3.latex(f'Método: {"Euler" if e == 0 else "Secante"}')
46+
set_resultados(st, pcr, P, tensao_normal_critica, tensao_normal_aplicada, v_max, FS, e, ecr2, abaco, gerar_abaco_completo)
11147

112-
set_chart(col4, ecr2, abaco, gerar_abaco_completo)
113-
set_table(col5, ecr2, abaco)

src/utils.py

Lines changed: 190 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,203 @@
11
import plotly.graph_objects as go
22

3-
def get_footer():
4-
style = """
5-
<style>
6-
# MainMenu {visibility: hidden;}
7-
footer {visibility: hidden;}
8-
.stApp { bottom: 0px; }
9-
</style>
10-
"""
11-
return style
12-
13-
def set_chart(col_widget, ecr2_base: float, abaco: dict, gerar_abaco_completo: bool) -> None:
3+
from math import sqrt
4+
import numpy as np
5+
6+
def reset_config(st) -> None:
7+
8+
def _get_footer():
9+
style = """
10+
<style>
11+
# MainMenu {visibility: hidden;}
12+
footer {visibility: hidden;}
13+
.stApp { bottom: 0px; }
14+
</style>
15+
"""
16+
return style
1417

15-
fig = go.Figure()
18+
st.set_page_config(
19+
page_title="Calculadora",
20+
page_icon=":coffee:",
21+
layout="wide",
22+
initial_sidebar_state="expanded",
23+
menu_items = {
24+
'Get Help': 'mailto:[email protected]?subject=Ajuda%20-%20Calculadora%20de%20Tensão%20Crítica',
25+
'Report a bug': 'mailto:[email protected]?subject=BUG%20-%20Calculadora%20de%20Tensão%20Crítica',
26+
},
27+
)
28+
29+
st.markdown(_get_footer(), unsafe_allow_html=True)
30+
31+
def set_basic_info(st) -> None:
32+
33+
st.title('Calculadora - Tensão Crítica')
34+
35+
st.markdown("""
36+
37+
Feito por: Marcelo Cardozo &bull; [![GitHub](https://cdn.pixabay.com/photo/2022/01/30/13/33/github-6980894_1280.png)](https://github.com/marcelogcardozo)
38+
&bull; [![LinkedIn](https://scontent.fsdu25-1.fna.fbcdn.net/v/t39.30808-1/267422938_4880673518668256_5792791296770782057_n.png?stp=dst-png_p200x200&_nc_cat=108&ccb=1-7&_nc_sid=754033&_nc_ohc=FzJ49MszpDkAX_b3T44&_nc_ht=scontent.fsdu25-1.fna&cb_e2o_trans=t&oh=00_AfC1YK5ssU0tc3BQcFnYLlPAJFN8jotV5pf9JJc-ANb7pQ&oe=650DDC2B)](https://www.linkedin.com/in/marcelogcardozo/)
39+
40+
Versão: 1.0
41+
""")
42+
43+
st.markdown(
44+
"""
45+
<style>
46+
img {
47+
width: 25px; /* Define a largura da imagem */
48+
height: 25px; /* Define a altura da imagem */
49+
border-radius: 50%; /* Cria um efeito de círculo */
50+
}
51+
</style>
52+
""",
53+
unsafe_allow_html=True,
54+
)
55+
56+
st.subheader('Resultados')
57+
st.divider()
58+
59+
def set_sidebar_and_get_params(st) -> tuple:
60+
61+
def _set_dados_do_material() -> tuple:
62+
63+
st.sidebar.subheader('Dados do Material')
64+
E = st.sidebar.number_input('Módulo de Elasticidade (E) [GPa]', 0.0, None, 200.0) * 1000
65+
T_esc = st.sidebar.number_input('Tensão de Escoamento ($\sigma_{y}$) [MPa]', 0.0, None, 250.0)
66+
67+
return E, T_esc
68+
69+
def _set_dados_secao_transversal() -> tuple:
70+
71+
st.sidebar.subheader('Dados da Seção Transversal')
72+
A = st.sidebar.number_input('Área (A) [mm²]', 0.0, None, 0.0)
73+
col1, col2 = st.sidebar.columns([0.4, 0.6])
74+
select_box_I_r = col1.selectbox('Inércia ou Raio de Giração', ['I [mm⁴]', 'r [mm]'], label_visibility='collapsed')
75+
value_I_r = col2.number_input('uma_label_qualquer', 0.0, None, 0.0, label_visibility='collapsed')
1676

17-
for ecr2, pontos in abaco.items():
77+
if select_box_I_r == 'I [mm⁴]':
78+
I = value_I_r
79+
try:
80+
r = sqrt(I / A)
81+
except ZeroDivisionError:
82+
r = 0.0
83+
else:
84+
r = value_I_r
85+
I = A * r**2
1886

19-
xs = [p.ler for p in pontos]
20-
ys = [p.pa for p in pontos]
87+
c = st.sidebar.number_input('Dist. da LN à Fibra de Maior Compressão (c) [mm]', 0.0, None, 0.0)
2188

22-
dash = 'dash' if (ecr2 == ecr2_base and gerar_abaco_completo) else None
23-
line_trace = go.Line(x=xs, y=ys, name=f"{ecr2:.2f}", line=dict(dash=dash))
89+
return A, I, r, c
2490

25-
fig.add_trace(line_trace)
91+
def _set_dados_do_caso() -> tuple:
2692

27-
fig.update_layout(
28-
title= 'Ábaco de Euler e Secante',
29-
xaxis_title="Le/r",
30-
yaxis_title="P/A",
31-
legend_title="Ecr2",
32-
yaxis_range=[0, 300.1],
33-
xaxis_range=[0, 200.1],
34-
)
93+
st.sidebar.subheader('Dados do caso')
94+
95+
col1, col2 = st.sidebar.columns([0.4, 0.6])
96+
97+
sbox_P = col1.selectbox('uma_label', ['P [kN]', 'FS'], label_visibility='collapsed') #st.sidebar.number_input('Carga aplicada (P) [kN]', 0.0, None, 0.0)
98+
value_P = col2.number_input('uma_label2', 0.0, None, 0.0, label_visibility='collapsed')
99+
100+
if sbox_P == 'P [kN]':
101+
P = value_P
102+
FS = 0
103+
else:
104+
FS = value_P
105+
P = 0
106+
107+
col1, col2 = st.sidebar.columns([0.4, 0.6])
108+
sbox_Le = col1.selectbox('Comprimento efetivo do elemento (Le)', ['Le [mm]', 'L [mm]'], label_visibility='collapsed')
109+
value_Le = col2.number_input('uma_label_qualquer2', 0.0, None, 0.0, label_visibility='collapsed')
110+
111+
if sbox_Le == 'L [mm]':
112+
k = st.sidebar.select_slider('Coeficiente de Flambagem (k)', [str(round(i,2)) for i in np.arange(0.5, 2.05, 0.05)])
113+
Le = float(k) * value_Le
114+
else:
115+
Le = value_Le
116+
k = 1.0
117+
118+
e = st.sidebar.number_input('Excentricidade (e) [mm]', 0.0, None, 0.0)
119+
120+
return P, FS, Le, k, e
121+
122+
def _set_gerar_abaco_completo_params() -> tuple:
123+
124+
gerar_abaco_completo = st.sidebar.checkbox('Gerar ábaco completo', value=False, key='gerar_abaco')
125+
126+
if gerar_abaco_completo:
127+
128+
faixa_ecr2 = st.sidebar.slider(r'Faixa do $ec/r²$', 0.0, 2.0, (0.0, 1.0), 0.1)
129+
de = faixa_ecr2[0]
130+
ate = faixa_ecr2[1]
131+
132+
razao = st.sidebar.number_input('Razão', 0.1, 2.0, 0.1)
133+
else:
134+
de = 0.0
135+
ate = 1.0
136+
razao = 0.1
137+
138+
return gerar_abaco_completo, de, ate, razao
139+
140+
# Parâmetros de entrada
141+
st.sidebar.title('Parâmetros de Entrada')
142+
143+
E, T_esc = _set_dados_do_material()
144+
A, I, r, c = _set_dados_secao_transversal()
145+
P, FS, Le, k, e = _set_dados_do_caso()
146+
abaco_completo, de, ate, razao = _set_gerar_abaco_completo_params()
147+
148+
return E, T_esc, A, I, r, c, P, FS, Le, k, e, abaco_completo, de, ate, razao
149+
150+
def set_resultados(st, pcr, P, tensao_normal_critica, tensao_normal_aplicada, v_max, FS, e, ecr2, abaco, gerar_abaco_completo) -> None:
151+
152+
def set_chart(col_widget, ecr2_base: float, abaco: dict, gerar_abaco_completo: bool) -> None:
153+
154+
fig = go.Figure()
155+
156+
for ecr2, pontos in abaco.items():
157+
158+
xs = [p.ler for p in pontos]
159+
ys = [p.pa for p in pontos]
160+
161+
dash = 'dash' if (ecr2 == ecr2_base and gerar_abaco_completo) else None
162+
line_trace = go.Scatter(x=xs, y=ys, name=f"{ecr2:.2f}", mode='lines', line=dict(dash=dash))
163+
164+
fig.add_trace(line_trace)
165+
166+
fig.update_layout(
167+
title= 'Ábaco de Euler e Secante',
168+
xaxis_title="Le/r",
169+
yaxis_title="P/A",
170+
legend_title="Ecr2",
171+
yaxis_range=[0, 300.1],
172+
xaxis_range=[0, 200.1],
173+
)
174+
175+
col_widget.plotly_chart(fig, use_container_width=True)
176+
177+
def set_table(col_widget, ecr2, abaco) -> None:
178+
179+
data_for_dataframe = {
180+
'Le/r': [round(p.ler, 2) for p in abaco[ecr2]],
181+
'P/A': [round(p.pa, 2) for p in abaco[ecr2]],
182+
}
183+
184+
col_widget.dataframe(data_for_dataframe)
185+
186+
col1, col2, col3 = st.columns(3)
187+
col4, col5 = st.columns([0.85, 0.15])
188+
189+
col1.latex('P_{cr} = '+f'{pcr:.2f} kN')
190+
col1.latex(f'P = {P:.2f} kN')
191+
192+
col2.latex('\sigma_{cr} = '+f'{tensao_normal_critica:.2f} MPa')
193+
col2.latex(f'\sigma = {tensao_normal_aplicada:.2f} MPa')
194+
col2.latex('V_{max} = '+f'{v_max:.2f} mm')
35195

36-
col_widget.plotly_chart(fig, use_container_width=True)
196+
col3.latex(f'FS = {FS:.2f}')
197+
col3.latex(f'Método: {"Euler" if e == 0 else "Secante"}')
37198

199+
set_chart(col4, ecr2, abaco, gerar_abaco_completo)
200+
set_table(col5, ecr2, abaco)
38201

39-
def set_table(col_widget, ecr2, abaco) -> None:
40202

41-
data_for_dataframe = {
42-
'Le/r': [round(p.ler, 2) for p in abaco[ecr2]],
43-
'P/A': [round(p.pa, 2) for p in abaco[ecr2]],
44-
}
45203

46-
col_widget.dataframe(data_for_dataframe)

0 commit comments

Comments
 (0)