Source code for PySS.polygonal

# -*- coding: utf-8 -*-

"""
A class for the Eurocode related structural calculations of an RCPS.

"""
import numpy as np
import PySS.steel_design as sd


[docs]class TheoreticalSpecimen(sd.Part): """ Properties and calculations of a theoretical (ideal geometry) polygonal column. """
[docs] def __init__(self, geometry=None, cs_props=None, material=None, struct_props=None, bc_loads=None): super().__init__( geometry, cs_props, material, struct_props, bc_loads)
[docs] @classmethod def from_geometry( cls, n_sides, r_cyl, thickness, length, f_y_nominal, fab_class, a_b=3., f_y_real=None ): """ Create theoretical polygonal column object for given geometric data. The constructor calculates properties of the polygonal column object (cross-section props, resistance, geometric props etc). The calculated data is then used to construct an object. This is the basic alternative constructor, several other alternative constructors are defined for different cases of input data. All of the following alternative constructors are calling this one to create the object after having performed the necessary geometrical pre-calculations. Parameters ---------- n_sides : int Number of sides of the polygon cross-section. r_cyl : float Radius of the circle circumscribed to the polygon. thickness : float Thickness of the cross-section. length : float Length of the column. f_y_nominal : float Yield stress of the material. fab_class : {'fcA', 'fcB', 'fcC'} Fabrication class, as described in EN 1996-1-6. It is used in the calculation of the buckling resistance of the cylinder of equal thickness-perimeter. a_b : float Corner bending radius over thickness ratio. f_y_real : float, optional Measured yield stress. Default uses the nominal value. """ if f_y_real is None: f_y = f_y_nominal else: f_y = f_y_real # Create material material = sd.Material(210000., 0.3, f_y_nominal, f_y_real) # Bending radius r_b = a_b * thickness # Theta angle theta = np.pi / n_sides # Radius of the polygon's circumscribed circle r_p = (np.pi * r_cyl + a_b * thickness * (n_sides * np.tan(theta) - np.pi)) / (n_sides * np.sin(theta)) # Width of each side bbbb = 2 * r_p * np.sin(theta) # Width of the corner bend half arc projection on the plane of the facet b_c = r_b * np.tan(theta) # Flat width of each facet (excluding the bended arcs) cccc = bbbb - 2 * b_c # Buckling width of each side as per EN 1993-1-3 g_r = r_b * (np.tan(theta)-np.sin(theta)) ccc3 = bbbb - 2 * g_r # Cross sectional area area = 2 * np.pi * r_cyl * thickness # Moment of inertia b_o = bbbb + thickness * np.tan(theta) alfa = thickness * np.tan(theta) / b_o moi = (n_sides * b_o ** 3 * thickness / 8) * (1 / 3 + 1 / (np.tan(theta) ** 2)) * (1 - 3 * alfa + 4 * alfa ** 2 - 2 * alfa ** 3) # Effective cross section area corner_area = 2 * np.pi * r_b * thickness a_eff = n_sides * sd.calc_a_eff(thickness, cccc, f_y) + corner_area # Gather all cross sectional properties in an appropriate class cs_props = sd.CsProps( area=area, a_eff=a_eff, xc=0., yc=0., moi_xx=moi, moi_yy=moi, moi_xy=0., moi_1=moi, moi_2=moi) # cs_props = sd.CsProps.from_cs_sketch(cs_sketch) cs_props.max_dist = r_p cs_props.min_dist = np.sqrt(r_p ** 2 - (bbbb / 2) ** 2) # Polar coordinate of the polygon vertices on the cross-section plane phii = [] for i_index in range(n_sides): phii.append(i_index * theta) # Polygon corners coordinates. x_corners = tuple(r_p * np.cos(phii)) y_corners = tuple(r_p * np.sin(phii)) # Cross-sectional properties nodes = [x_corners, y_corners] elem = [ list(range(0, len(x_corners))), list(range(1, len(x_corners))) + [0], len(x_corners) * [thickness] ] cs_sketch = sd.CsSketch(nodes, elem) geometry = sd.Geometry(cs_sketch, length, thickness) # Additional geometric properties (exclusive to the polygonal) geometry.r_circle = r_cyl geometry.r_circumscribed = r_p geometry.facet_width = bbbb geometry.facet_flat_width = cccc geometry.n_sides = n_sides geometry.r_bend = r_b lmbda_y = sd.lmbda_flex( length, cs_props.a_eff, cs_props.moi_1, kapa_bc=1., e_modulus=material.e_modulus, f_yield=material.f_y_nominal ) lmbda_z = lmbda_y # Plate classification (acc. to EC3-1-1) p_classification = cccc / (material.epsilon * thickness) # Critical stress acc. to plate theory. sigma_cr_plate = sd.sigma_cr_plate(thickness, bbbb - 3*thickness) # Critical load acc. to plate theory. n_cr_plate = cs_props.area * sigma_cr_plate # Axial compression resistance, Npl (acc. to EC3-1-5) n_pl_rd = cs_props.a_eff * f_y # Buckling load n_b_rd = sd.n_b_rd(geometry.length, cs_props.a_eff, cs_props.moi_1, f_y, "d") # Buckling stress (account for both flex and local) sigma_b_rd_plate = n_b_rd / cs_props.area ############################################################################## # Plate classification (acc. to EC3-1-3) pc_classification = ccc3 / (material.epsilon * thickness) # Critical stress acc. to plate theory. sigma_cr_platec = sd.sigma_cr_plate(thickness, ccc3) # Critical load acc. to plate theory for CF sections. n_cr_platec = cs_props.area * sigma_cr_platec # Axial compression resistance, Npl (acc. to EC3-1-3) # rho3 = sd.calc_a_eff(thickness, ccc3, f_y) / (thickness * ccc3) # cs_props.a_eff3 = n_sides * rho3 * cccc * thickness + corner_area cs_props.a_eff3 = n_sides * sd.calc_a_eff(thickness, ccc3, f_y) n_pl_rdc = cs_props.a_eff3 * f_y # Buckling load n_b_rdc = sd.n_b_rd(geometry.length, cs_props.a_eff3, cs_props.moi_1, f_y, "d") # Buckling stress (account for both flex and local) sigma_b_rd_platec = n_b_rdc / cs_props.area ############################################################################## # Tube classification slenderness acc. to EC3-1-1 t_classification = 2 * r_cyl / (material.epsilon ** 2 * thickness) # Length categorisation acc. to EC3-1-1, new draft proposal lenca = sd.shell_length_category(r_cyl, thickness, length) lenca_new = sd.shell_length_category_new(r_cyl, thickness, length) # Critical stress acc. to shell theory. sigma_cr_shell = sd.sigma_x_rcr(thickness, r_cyl, length) sigma_cr_shell_new = sd.sigma_x_rcr_new(thickness, r_cyl, length) # Critical load acc. to shell theory. n_cr_shell = sd.n_cr_shell(thickness, r_cyl, length) n_cr_shell_new = sd.n_cr_shell_new(thickness, r_cyl, length) # Characteristic compression stress of equivalent cylindrical shell (acc. to EC3-1-6) sigma_b_rk_shell = sd.sigma_x_rk(thickness, r_cyl, length, f_y, fab_quality=fab_class) sigma_b_rk_shell_new = sd.sigma_x_rk_new(thickness, r_cyl, length, f_y, fab_quality=fab_class) # Characteristic compression resistance of equivalent cylindrical shell (acc. to EC3-1-6) n_b_rk_shell = cs_props.area * sigma_b_rk_shell n_b_rk_shell_new = cs_props.area * sigma_b_rk_shell_new # Compression stress of equivalent cylindrical shell (acc. to EC3-1-6) sigma_b_rd_shell = sd.sigma_x_rd(thickness, r_cyl, length, f_y, fab_quality=fab_class) sigma_b_rd_shell_new = sd.sigma_x_rd_new(thickness, r_cyl, length, f_y, fab_quality=fab_class) # Compression resistance of equivalent cylindrical shell (acc. to EC3-1-6) n_b_rd_shell = cs_props.area * sigma_b_rd_shell n_b_rd_shell_new = cs_props.area * sigma_b_rd_shell_new struct_props = sd.StructProps( t_classification=t_classification, p_classification=p_classification, pc_classification=pc_classification, lmbda_y=lmbda_y, lmbda_z=lmbda_z, n_cr_plate=n_cr_plate, sigma_cr_plate=sigma_cr_plate, n_pl_rd=n_pl_rd, sigma_b_rd_plate=sigma_b_rd_plate, n_b_rd_plate=n_b_rd, sigma_cr_shell=sigma_cr_shell, sigma_cr_shell_new=sigma_cr_shell_new, lenca=lenca, lenca_new=lenca_new, n_cr_shell=n_cr_shell, n_cr_shell_new=n_cr_shell_new, sigma_b_rk_shell=sigma_b_rk_shell, sigma_b_rk_shell_new=sigma_b_rk_shell_new, n_b_rk_shell=n_b_rk_shell, n_b_rk_shell_new=n_b_rk_shell_new, sigma_b_rd_shell=sigma_b_rd_shell, sigma_b_rd_shell_new=sigma_b_rd_shell_new, n_b_rd_shell=n_b_rd_shell, n_b_rd_shell_new=n_b_rd_shell_new, n_cr_platec=n_cr_platec, sigma_cr_platec=sigma_cr_platec, n_pl_rdc=n_pl_rdc, sigma_b_rd_platec=sigma_b_rd_platec, n_b_rd_platec=n_b_rdc ) return cls(geometry, cs_props, material, struct_props)
[docs] @classmethod def from_pclass_thickness_length( cls, n_sides, p_classification, thickness, length, f_y_nominal, fab_class, a_b=3., f_y_real=None ): """ Create theoretical polygonal column object for given plate slenderness, thickness and length. Uses the :func:`~PySS.polygonal.from_geometry`. Parameters ---------- n_sides : int Number of sides of the polygon cross-section. p_classification : float Facet slenderness, c/(ε*t). thickness : float Thickness of the cross-section. length : float Length of the column. f_y_nominal : float Yield stress of the material. fab_class : {'fcA', 'fcB', 'fcC'} Fabrication class, as described in EN 1996-1-6. It is used in the calculation of the buckling resistance of the cylinder of equal thickness-perimeter. a_b : float Thickness to bending radius ratio. f_y_real : float, optional Measured yield stress. Default uses the nominal value. """ # Epsilon for the material if f_y_real is None: epsilon = np.sqrt(235. / f_y_nominal) else: epsilon = np.sqrt(235. / f_y_real) # Radius of the equal perimeter cylinder #r_circle = (n_sides * thickness / np.pi) * ((p_classification * epsilon / 2) + arc_to_thickness * np.tan(np.pi / n_sides)) r_circle = thickness*(n_sides * p_classification * epsilon / (2*np.pi) + a_b) return cls.from_geometry( n_sides, r_circle, thickness, length, f_y_nominal, fab_class, f_y_real=f_y_real )
[docs] @classmethod def from_pclass_radius_length( cls, n_sides, r_cyl, p_classification, length, f_y_nominal, fab_class, a_b=3., f_y_real=None ): """ Create theoretical polygonal column object for given equivalent cylinder radius, plate slenderness and length. Uses the :func:`~PySS.polygonal.from_geometry`. Parameters ---------- n_sides : int Number of sides of the polygon cross-section. r_cyl : float Radius of the equivalent cylinder. p_classification : float Facet slenderness, c/(ε*t). length : float Length of the column. f_y_nominal : float Yield stress of the material. fab_class : {'fcA', 'fcB', 'fcC'} Fabrication class, as described in EN 1996-1-6. It is used in the calculation of the buckling resistance of the cylinder of equal thickness-perimeter. a_b : float Thickness to bending radius ratio. f_y_real : float, optional Measured yield stress. Default uses the nominal value. """ # Epsilon for the material if f_y_real is None: epsilon = np.sqrt(235. / f_y_nominal) else: epsilon = np.sqrt(235. / f_y_real) # Calculate the thickness thickness = r_cyl / ((n_sides * p_classification * epsilon / (2 * np.pi)) + a_b) return cls.from_geometry( n_sides, r_cyl, thickness, length, f_y_nominal, fab_class, f_y_real=f_y_real )
[docs] @classmethod def from_pclass_area_length( cls, n_sides, p_classification, area, length, f_y_nominal, fab_class, a_b=3, f_y_real=None ): """ Create theoretical polygonal column object for given equivalent cylinder radius, plate slenderness and length. Uses the :func:`~PySS.polygonal.from_geometry`. Parameters ---------- n_sides : int Number of sides of the polygon cross-section. p_classification : float Facet slenderness, c/(ε*t). area : float Cross-sectional area. length : float Length of the column. f_y_nominal : float Yield stress of the material. fab_class : {'fcA', 'fcB', 'fcC'} Fabrication class, as described in EN 1996-1-6. It is used in the calculation of the buckling resistance of the cylinder of equal thickness-perimeter. a_b : float Thickness to bending radius ratio. f_y_real : float, optional Measured yield stress. Default uses the nominal value. """ # Epsilon for the material if f_y_real is None: epsilon = np.sqrt(235. / f_y_nominal) else: epsilon = np.sqrt(235. / f_y_real) # Thickness thickness = np.sqrt(area / (n_sides * p_classification * epsilon + 2 * np.pi * a_b)) # Radius of equivalent cylinder r_cyl = area / (2 * np.pi * thickness) return cls.from_geometry( n_sides, r_cyl, thickness, length, f_y_nominal, fab_class, f_y_real=f_y_real )
[docs] @classmethod def from_radius_area_length( cls, n_sides, r_cyl, area, length, f_y_nominal, fab_class, a_b=3, f_y_real=None ): """ Create theoretical polygonal column object for given equivalent cylinder radius, area and length. Uses the :func:`~PySS.polygonal.from_geometry`. Parameters ---------- n_sides : int Number of sides of the polygon cross-section. r_cyl : float Radius of the equivalent cylinder. area : float Cross-sectional area. length : float Length of the column. f_y_nominal : float Yield stress of the material. fab_class : {'fcA', 'fcB', 'fcC'} Fabrication class, as described in EN 1996-1-6. It is used in the calculation of the buckling resistance of the cylinder of equal thickness-perimeter. a_b : float Thickness to bending radius ratio. f_y_real : float, optional Measured yield stress. Default uses the nominal value. """ thickness = area / (2 * np.pi *r_cyl) return cls.from_geometry( n_sides, r_cyl, thickness, length, f_y_nominal, fab_class, a_b=a_b, f_y_real=f_y_real )
[docs] @classmethod def from_radius_thickness_flexslend( cls, n_sides, r_cyl, thickness, lambda_flex, f_y_nominal, fab_class, a_b=3., f_y_real=None ): """ Create theoretical polygonal column object for given equivalent cylinder radius, thickness and flexural slenderness. Uses the :func:`~PySS.polygonal.from_geometry`. Parameters ---------- n_sides : int Number of sides of the polygon cross-section. r_cyl : float Radius of the equivalent cylinder. thickness : float Thickness of the cross-section. lambda_flex : float Flexural slenderness. f_y_nominal : float Yield stress of the material. fab_class : {'fcA', 'fcB', 'fcC'} Fabrication class, as described in EN 1996-1-6. It is used in the calculation of the buckling resistance of the cylinder of equal thickness-perimeter. a_b : float Thickness to bending radius ratio. f_y_real : float, optional Measured yield stress. Default uses the nominal value. """ if f_y_real is None: f_y = f_y_nominal else: f_y = f_y_real # Bending radius r_b = a_b * thickness # Theta angle theta = np.pi / n_sides # Radius of the polygon's circumscribed circle r_p = (np.pi * r_cyl + a_b * thickness * (n_sides * np.tan(theta) - np.pi)) / (n_sides * np.sin(theta)) # Width of each side bbbb = 2 * r_p * np.sin(theta) # Width of the corner bend half arc projection on the plane of the facet b_c = r_b * np.tan(theta) # Flat width of each facet (excluding the bended arcs) cccc = bbbb - 2 * b_c # Moment of inertia b_o = bbbb + thickness * np.tan(theta) alfa = thickness * np.tan(theta) / b_o moi = (n_sides * b_o ** 3 * thickness / 8) * (1 / 3. + 1 / (np.tan(theta) ** 2)) * ( 1 - 3 * alfa + 4 * alfa ** 2 - 2 * alfa ** 3) # Effective cross secion area corner_area = 2 * np.pi * r_b * thickness a_eff = n_sides * sd.calc_a_eff(thickness, cccc, f_y) + corner_area # Calculate column length for the given flexural slenderness. length = lambda_flex * np.pi * np.sqrt(210000. * moi / (a_eff * f_y)) return cls.from_geometry( n_sides, r_cyl, thickness, length, f_y_nominal, fab_class, a_b=a_b, f_y_real=f_y_real )
[docs] @classmethod def from_pclass_radius_flexslend( cls, n_sides, r_cyl, p_classification, lambda_flex, f_y_nominal, fab_class, a_b=3., f_y_real=None ): """ Create theoretical polygonal column object for given equivalent cylinder radius, plate classification and flexural slenderness. Uses the :func:`~PySS.polygonal.from_geometry`. Parameters ---------- n_sides : int Number of sides of the polygon cross-section. r_cyl : float Radius of the equivalent cylinder. p_classification : float Facet slenderness, c/(ε*t). lambda_flex : float Flexural slenderness. f_y_nominal : float Yield stress of the material. fab_class : {'fcA', 'fcB', 'fcC'} Fabrication class, as described in EN 1996-1-6. It is used in the calculation of the buckling resistance of the cylinder of equal thickness-perimeter. a_b : float Thickness to bending radius ratio. f_y_real : float, optional Measured yield stress. Default uses the nominal value. """ # Epsilon for the material if f_y_real is None: epsilon = np.sqrt(235. / f_y_nominal) else: epsilon = np.sqrt(235. / f_y_real) # Calculate the thickness thickness = r_cyl / ((n_sides * p_classification * epsilon / (2 * np.pi)) + a_b) return cls.from_radius_thickness_flexslend( n_sides, r_cyl, thickness, lambda_flex, f_y_nominal, fab_class, a_b=a_b, f_y_real=f_y_real )
[docs] @classmethod def from_pclass_area_flexslend( cls, n_sides, p_classification, area, lambda_flex, f_y_nominal, fab_class, a_b=3., f_y_real=None ): """ Create theoretical polygonal column object for given plate classification, area and flexural slenderness. Uses the :func:`~PySS.polygonal.from_geometry`. Parameters ---------- n_sides : int Number of sides of the polygon cross-section. p_classification : float Facet slenderness, c/(ε*t). area : float Cross-sectional area. lambda_flex : float Flexural slenderness. f_y : float Yield stress of the material. fab_class : {'fcA', 'fcB', 'fcC'} Fabrication class, as described in EN 1996-1-6. It is used in the calculation of the buckling resistance of the cylinder of equal thickness-perimeter. a_b : float Thickness to bending radius ratio. f_y_real : float, optional Measured yield stress. Default uses the nominal value. """ # Epsilon for the material if f_y_real is None: epsilon = np.sqrt(235. / f_y_nominal) else: epsilon = np.sqrt(235. / f_y_real) # Thickness thickness = np.sqrt(area / (n_sides * p_classification * epsilon + 2 * np.pi * a_b)) # Radius of equivalent cylinder r_cyl = area / (2 * np.pi * thickness) return cls.from_radius_thickness_flexslend( n_sides, r_cyl, thickness, lambda_flex, f_y_nominal, fab_class, a_b=3, f_y_real=f_y_real )
[docs] @staticmethod def behaviour_limit(fy, uu): """ Calculate the limit between plated and shell behaviour according to the functions derived in my thesis. Parameters ---------- fy : float Yield stress. uu : float Returns ------- :obj:`PySS.analytic_geometry.Line2D` """ kapa = (1193 - fy) / 50 zeta = 364e3*uu**2-5e3*uu+21 ksi = -zeta*kapa+27 return(ag.Line2D.from_line_coeff(-zeta, 1, -ksi))
[docs] @staticmethod def plate_behaviour(nv, pc, fy, uu): kapa = (1193 - fy) / 50 zeta = 364e3*uu**2-5e3*uu+21 ksi = -zeta*kapa+27 return(pc-zeta*nv > ksi)