Comprobación de miembros sujetos a fatiga según FEM 2131/2132 (6 y final)

7 minutos de lectura

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.

\[\dfrac{\sigma_{x,max}}{\sigma_{xa}} = \dfrac{-130}{-140,4} = 0,93\] \[\dfrac{\sigma_{y,max}}{\sigma_{ya}} = \dfrac{-1}{-90,0} = 0,01\] \[\frac{\tau_{xy,max}}{\tau_{a}} = \frac{6}{115,5} = 0,05\] \[\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 =\] \[\left(\frac{-130}{-140,4}\right)^2 + \left(\frac{-1}{-90,0}\right)^2 - \frac{(-130) \cdot (-1)}{|-140,4| \cdot |-90,0|} + \left(\frac{6}{115,5}\right)^2 = 0,85\] \[\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} =\] \[\sqrt{\left(\frac{-130}{-140,4}\right)^2 + \left(\frac{-1}{-90,0}\right)^2 - \frac{(-130) \cdot (-1)}{|-140,4| \cdot |-90,0|} + \left(\frac{6}{115,5}\right)^2} = 0,92\]

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.

\[\dfrac{\sigma_{x,max}}{\sigma_{xa}} = \dfrac{-79}{-35,6} = 2,22\] \[\dfrac{\sigma_{y,max}}{\sigma_{ya}} = \dfrac{-1}{-90,0} = 0,01\] \[\dfrac{\tau_{xy,max}}{\tau_{a}} = \dfrac{-6}{91} = -0,07\] \[\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 =\] \[\left(\frac{-79}{-35,6}\right)^2 + \left(\frac{-1}{-66,6}\right)^2 - \frac{(-79) \cdot (-1)}{|-35,6| \cdot |-66,6|} + \left(\frac{-6}{91,0}\right)^2 = 4,90\] \[\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} =\] \[\sqrt{\left(\frac{-79}{-35,6}\right)^2 + \left(\frac{-1}{-66,6}\right)^2 - \frac{(-79) \cdot (-1)}{|-35,6| \cdot |-66,6|} + \left(\frac{-6}{91,0}\right)^2} = 2,21\]

Colclusión

Para evaluar la idoneidad de las barras de la estructura estudiada frente a la fatiga se han seguido los siguientes pasos:

  1. Se ha partido de unos datos dispuestos en un DataFrame.
  2. Se ha definido el acero estructural de la estructura.
  3. Se han obtenido los ratios \(\kappa\) entre las tensiones extremas.
  4. Se han comprobado las barras sometidas a tracción o compresión.
  5. Se ha comprobado igualmente la tensión de cortadura de las barras.
  6. 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.

Etiquetas: ,

Actualizado:

Comentar