Comprobación de miembros sujetos a fatiga según FEM 2131/2132 (6 y final)
Cargas combinadas de tracción, compresión y cortadura
Y ya para terminar es necesario comprobar la combinación de las diferentes acciones de tracción, compresión y cortadura.
En este caso se determinan las tensiones admisibles por fatiga para cada carga normal en tracción o compresión \(\sigma_{xa}\), \(\sigma_{ya}\) y cortante \(\tau_{xya}\) suponiendo que cada una actúa por separado. Para ello se verifican las tres condiciones siguientes:
\[\frac{\sigma_{x,max}}{\sigma_{xa}} \le 1\] \[\frac{\sigma_{y,max}}{\sigma_{ya}} \le 1\] \[\frac{\tau_{xy,max}}{\tau_{xya}} \le 1\]Además de comprobar cada carga que se supone que actúa aisladamente, la norma recomienda que se compruebe la siguiente relación:
\[\left(\frac{\sigma_{x,max}}{\sigma_{xa}}\right)^2 + \left(\frac{\sigma_{y,max}}{\sigma_{ya}}\right)^2 - \frac{\sigma_{x,max} \cdot \sigma_{y,max}}{|\sigma_{xa}| \cdot |\sigma_{ya}|} + \left(\frac{\tau_{xy,max}}{\tau_{xya}}\right)^2 \le 1\]Como esta desigualdad constituye un requisito bastante estricto, se aceptan valores ligeramente superiores a 1, pero en este caso es necesario comprobar la relación:
\[\sqrt{\left(\frac{\sigma_{x,max}}{\sigma_{xa}}\right)^2 + \left(\frac{\sigma_{y,max}}{\sigma_{ya}}\right)^2 - \frac{\sigma_{x,max} \cdot \sigma_{y,max}}{|\sigma_{xa}| \cdot |\sigma_{ya}|} + \left(\frac{\tau_{xy,max}}{\tau_{xya}}\right)^2} \le 1,05\]El proceso de creación de las clases para el cálculo de la tensión de cortadura será similar al empleado en los casos anteriores. El objetivo de organizar el código de esta manera es una mezcla de programación defensiva y organización del código para el mantenimiento.
- En una primera clase llamada
DataFrame
obtendré los valores básicos para calcular las tensiones admisibles. - En una segunda clase llamada
Formulae
definiré el formulario para el cálculo. - Y en un tercera y última clase
PermissibleStress
obtendré las tensiones admisibles según las diferentes condiciones de cálculo.
La clase DataFrame
contiene la variable de instancia df
con los datos de estudio de la fatiga. Los métodos de la clase DataFrame
son los getters de las variables del cálculo.
class DataFrame:
"""
Pandas DataFrame with the data for the
calculation of the stresses for fatigue.
"""
def __init__(self, df):
"""
Asumes df is the pandas DataFrame
with the data for the calculation
of the stresses for fatigue, get
the values of the columns.
Parameters
----------
df : pandas DataFrame ; data for
the calculation of the stresses for
fatigue.
"""
self.df = df
def get_sigma_x_max(self):
"""Getter of sigma_x_max."""
return self.df['sigma_x_max_[MPa]'].copy()
def get_sigma_y_max(self):
"""Getter of sigma_y_max."""
return self.df['sigma_y_max_[MPa]'].copy()
def get_tau_xy_max(self):
"""Getter of tau_xy_max."""
return self.df['tau_xy_max_[MPa]'].copy()
def get_sigma_tx(self):
"""Getter of sigma_tx."""
return self.df['sigma_tx_[MPa]'].copy()
def get_sigma_cx(self):
"""Getter of sigma_cx."""
return self.df['sigma_cx_[MPa]'].copy()
def get_sigma_ty(self):
"""Getter of sigma_ty."""
return self.df['sigma_ty_[MPa]'].copy()
def get_sigma_cy(self):
"""Getter of sigma_cy."""
return self.df['sigma_cy_[MPa]'].copy()
def get_tau_a(self):
"""Getter of tau_a."""
return self.df['tau_a_[MPa]'].copy()
La segunda clase Formulae
hereda de la clase DataFrame
los atributos para operar.
class Formulae(DataFrame):
"""
Formulae for de permissible combined
stresses for fatigue with tensile,
comprensive and shear loads according
to FEM 2131/2132.
"""
def __init__(self, df):
"""
Asumes df has the data for the
calculation of the stresses for
fatigue, get the permissible
combined stresses for fatigue.
Parameters
----------
df : pandas DataFrame : data for
the calculation.
"""
DataFrame.__init__(self, df)
self.sigma_x_max = self.get_sigma_x_max()
self.sigma_y_max = self.get_sigma_y_max()
self.tau_xy_max = self.get_tau_xy_max()
self.sigma_tx = self.get_sigma_tx()
self.sigma_cx = self.get_sigma_cx()
self.sigma_ty = self.get_sigma_ty()
self.sigma_cy = self.get_sigma_cy()
self.tau_a = self.get_tau_a()
Primero había que comprobar las tensiones admisibles por fatiga para cada carga normal en tracción o compresión \(\sigma_{xa}\), \(\sigma_{ya}\) y cortante \(\tau_{xya}\) suponiendo que cada una actúa por separado. Recordemos primero las fórmulas.
\[\frac{\sigma_{x,max}}{\sigma_{xa}} \le 1\] \[\frac{\sigma_{y,max}}{\sigma_{ya}} \le 1\] \[\frac{\tau_{xy,max}}{\tau_{xya}} \le 1\]Y este es el código equivalente:
def permissible_stress(self, sigma_max, sigma_t, sigma_c):
"""
Permissible stress.
For sigma_max in tension -> permissible stress = sigma_t
For sigma_max in compression -> permissible stress = sigma_c
Sigma_max in tension ≥ 0 (positive value)
Sigma_max in compression < 0 (negative value)
"""
sigma = sigma_t.where(sigma_max >=0, sigma_c)
return sigma
def ratio(self, sigma_max, sigma_t, sigma_c):
"""Stress ratio."""
sigma_a = self.permissible_stress(sigma_max, sigma_t, sigma_c)
return sigma_max / sigma_a
def ratio_sigma_x(self):
"""Stress ratio for sigma_x."""
ratio = self.ratio(self.sigma_x_max, self.sigma_tx, self.sigma_cx)
return ratio
def ratio_sigma_y(self):
"""Stress ratio for sigma_y."""
ratio = self.ratio(self.sigma_y_max, self.sigma_ty, self.sigma_cy)
return ratio
def ratio_tau_xy(self):
"""Stress ratio for tau_xy."""
ratio = self.tau_xy_max.abs() / self.tau_a
return ratio
La primera comprobación de las cargas actuando en combinación es
\[\left(\frac{\sigma_{x,max}}{\sigma_{xa}}\right)^2 + \left(\frac{\sigma_{y,max}}{\sigma_{ya}}\right)^2 - \frac{\sigma_{x,max} \cdot \sigma_{y,max}}{|\sigma_{xa}| \cdot |\sigma_{ya}|} + \left(\frac{\tau_{xy,max}}{\tau_{xya}}\right)^2 \le 1\]Traducido a código:
def ratio_1(self):
"""
Combined stress ratio.
First option (formula (5) in
FEM 2131/2132, 3-4.5.1.3).
"""
ratio_s_x = self.ratio_sigma_x()
ratio_s_y = self.ratio_sigma_y()
ratio_t_xy = self.ratio_tau_xy()
permissible_stress_xa = self.permissible_stress(
self.sigma_x_max, self.sigma_tx, self.sigma_cx
)
permissible_stress_ya = self.permissible_stress(
self.sigma_y_max, self.sigma_ty, self.sigma_cy
)
ratio_s_xy = \
self.sigma_x_max * self.sigma_y_max / \
(permissible_stress_xa * permissible_stress_ya).abs()
r1 = ratio_s_x**2 + ratio_s_y**2 - ratio_s_xy + ratio_t_xy**2
return r1
Recordemos la segunda condición:
\[\sqrt{\left(\frac{\sigma_{x,max}}{\sigma_{xa}}\right)^2 + \left(\frac{\sigma_{y,max}}{\sigma_{ya}}\right)^2 - \frac{\sigma_{x,max} \cdot \sigma_{y,max}}{|\sigma_{xa}| \cdot |\sigma_{ya}|} + \left(\frac{\tau_{xy,max}}{\tau_{xya}}\right)^2} \le 1,05\] def ratio_2(self):
"""
Combined stress ratio.
Second option (formula in footnote
*(1) in FEM 2131/2132, 3-4.5.1.3).
"""
r1 = self.ratio_1()
r2 = r1**(0.5)
return r2
Finalmente se ejectua el código.
stress = PermissibleStress(df)
permissible_stress_sigma_x = stress.get_permissible_stress_sx()
permissible_stress_sigma_y = stress.get_permissible_stress_sy()
permissible_stress_tau_xy = stress.get_permissible_stress_txy()
ratio_sigma_x = stress.get_ratio_sigma_x()
ratio_sigma_y = stress.get_ratio_sigma_y()
ratio_tau_xy = stress.get_ratio_tau_xy()
ratio_1 = stress.get_ratio_1()
ratio_2 = stress.get_ratio_2()
df['sigma_xa_[MPa]'] = round(permissible_stress_sigma_x, 2)
df['sigma_ya_[MPa]'] = round(permissible_stress_sigma_y, 2)
df['tau_a_[MPa]'] = round(permissible_stress_tau_xy, 2)
df['ratio_s_x'] = round(ratio_sigma_x, 2)
df['ratio_s_y'] = round(ratio_sigma_y, 2)
df['ratio_t_xy'] = round(ratio_tau_xy, 2)
df['ratio_1'] = round(ratio_1, 2)
df['ratio_2'] = round(ratio_2, 2)
df['Validate'] = np.where(
(df['ratio_1'] <= 1.0) | (df['ratio_2'] <= 1.05),
'yes', 'no'
)
Tensiones máximas:
cols = [
'bar', 'node', 'component_group', 'notch_effect',
'sigma_x_max_[MPa]', 'sigma_y_max_[MPa]', 'tau_xy_max_[MPa]',
'sigma_xa_[MPa]', 'sigma_ya_[MPa]', 'tau_a_[MPa]'
]
df[cols]
bar | node | component_group | notch_effect | sigma_x_max_[MPa] | sigma_y_max_[MPa] | tau_xy_max_[MPa] | sigma_xa_[MPa] | sigma_ya_[MPa] | tau_a_[MPa] | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | E8 | K3 | -130 | -1 | 6 | -140.4 | -90.0 | 115.5 |
1 | 2 | 2 | E8 | K3 | 5 | 2 | 1 | 109.6 | 124.2 | 115.5 |
2 | 3 | 3 | E7 | K4 | -79 | -1 | -6 | -35.6 | -66.6 | 91.0 |
3 | 4 | 4 | E6 | K4 | -22 | 3 | 9 | -244.9 | 55.9 | 135.3 |
4 | 5 | 5 | E7 | K2 | -100 | -4 | 0 | -100.1 | -124.2 | 131.4 |
5 | 6 | 6 | E8 | K4 | -99 | 0 | 3 | -114.9 | 45.0 | 94.5 |
6 | 7 | 7 | E8 | K4 | -46 | 3 | 5 | -31.8 | 36.8 | 82.5 |
7 | 8 | 8 | E8 | K4 | -17 | -5 | 7 | -56.7 | -180.7 | 135.3 |
8 | 9 | 9 | E6 | K0 | 54 | 5 | 10 | 137.7 | 167.8 | 93.6 |
9 | 10 | 10 | E6 | K4 | 102 | 0 | -3 | 234.3 | 68.3 | 135.3 |
Ratios:
cols = [
'bar', 'node', 'component_group', 'notch_effect',
'ratio_s_x', 'ratio_s_y', 'ratio_t_xy', 'ratio_1', 'ratio_2', 'Validate'
]
df[cols]
bar | node | component_group | notch_effect | ratio_s_x | ratio_s_y | ratio_t_xy | ratio_1 | ratio_2 | Validate | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | E8 | K3 | 0.93 | 0.01 | 0.05 | 0.85 | 0.92 | yes |
1 | 2 | 2 | E8 | K3 | 0.05 | 0.02 | 0.01 | 0.00 | 0.04 | yes |
2 | 3 | 3 | E7 | K4 | 2.22 | 0.02 | 0.07 | 4.90 | 2.21 | no |
3 | 4 | 4 | E6 | K4 | 0.09 | 0.05 | 0.07 | 0.02 | 0.14 | yes |
4 | 5 | 5 | E7 | K2 | 1.00 | 0.03 | 0.00 | 0.97 | 0.98 | yes |
5 | 6 | 6 | E8 | K4 | 0.86 | 0.00 | 0.03 | 0.74 | 0.86 | yes |
6 | 7 | 7 | E8 | K4 | 1.45 | 0.08 | 0.06 | 2.22 | 1.49 | no |
7 | 8 | 8 | E8 | K4 | 0.30 | 0.03 | 0.05 | 0.09 | 0.29 | yes |
8 | 9 | 9 | E6 | K0 | 0.39 | 0.03 | 0.11 | 0.15 | 0.39 | yes |
9 | 10 | 10 | E6 | K4 | 0.44 | 0.00 | 0.02 | 0.19 | 0.44 | yes |
Parece que en algunas barras de nuestro modelo de cálculo tenemos un problema con la fatiga.
Para validar los resultados compruebo la barra 1 con el índice 0 del DataFrame
.
Voy a completar la verificación con una barra que está por encima del límite admisible de la fatiga. Compruebo la barra 3 con el índice 2 del DataFrame
.
Colclusión
Para evaluar la idoneidad de las barras de la estructura estudiada frente a la fatiga se han seguido los siguientes pasos:
- Se ha partido de unos datos dispuestos en un
DataFrame
. - Se ha definido el acero estructural de la estructura.
- Se han obtenido los ratios \(\kappa\) entre las tensiones extremas.
- Se han comprobado las barras sometidas a tracción o compresión.
- Se ha comprobado igualmente la tensión de cortadura de las barras.
- Finalmente se ha comprobado si las tensiones combinadas están dentro de los límites admisibles.
Un muestra de un código completo se puede encontrar en el siguiente repositorio de GitHub.
Comentar