class Z_Section: """ This is basically just a fixture for testing purposes. It's called by the actual pytest fixtures to generate the Z-sections for analysis. We have this class for fixtures, just to have a method for the load application, and simpler fixtures, along with the same base for multiple Z_Sections. """ def __init__(self, DIM1, DIM2, DIM3, DIM4, shift, m, name): # Setup the analysis, and calculate properties base_geom = nastran_sections.nastran_zed(DIM1, DIM2, DIM3, DIM4) self.geom = base_geom.shift_section(*shift) self.geom = self.geom.create_mesh(mesh_sizes=[m]) self.xsect = Section(self.geom) self.xsect.calculate_geometric_properties() # This plotting code was just for verifying the section offsets. # ax = self.xsect.plot_centroids(pause=False, render=False) # ax.grid(1, which='both', linestyle=':') # fig = ax.get_figure() # fig.savefig(f'{name}_geom.png') def apply_load(self, v): """ This method applies the suplied load to the section. v is a list-like with the first entry being Mxx, and second entry Myy. """ self.xsect.calculate_warping_properties() self.stress = self.xsect.calculate_stress(Mxx=v[0], Myy=v[1])
def get_section_j(geom, ms, plot_geom=False): geom.create_mesh(mesh_sizes=[ms]) section = Section(geom) if plot_geom: section.plot_mesh() section.calculate_geometric_properties() section.calculate_warping_properties() return section.get_j()
def test_custom_geometry_perimeter(): points = [[0, 0], [5, 0], [11, 8], [3, 2], [0, 2]] facets = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 0]] control_points = [[5, 5]] custom = Geometry.from_points(points, facets, control_points, holes=None) custom.create_mesh([100]) section = Section(custom) section.calculate_geometric_properties() assert section.get_perimeter() == 5 + 2 + 10 + 10 + 3
def test_warping_disjoint_warning(): rect = rectangular_section(d=50, b=50) circ = circular_section(d=50, n=32).shift_section(x_offset=125, y_offset=25) geom = (rect + circ).create_mesh([10]) sec = Section(geom) sec.calculate_geometric_properties() with pytest.warns(UserWarning): sec.calculate_warping_properties()
def test_compound_rectangular_offset(): rect1 = sections.rectangular_section(d=50, b=50) rect2 = sections.rectangular_section(d=50, b=50).align_to(rect1, "right") geom = rect1 + rect2 geom = geom.offset_perimeter(amount=-5, where="exterior") geom.create_mesh([50]) section = Section(geom) section.calculate_geometric_properties() area = 90 * 40 check.almost_equal(section.get_area(), area, rel=r_tol)
def test_box_girder_perimeter(): box_girder = steel_sections.box_girder_section(d=400, b_t=700, b_b=100, t_ft=20, t_fb=20, t_w=12) box_girder.create_mesh([100]) section = Section(box_girder) section.calculate_geometric_properties() assert section.get_perimeter() == 700 + 100 + 2 * 500
def test_plastic_centroid(): ## Test created in response to #114 # Since the section being tested is a compound geometry with two different # materials, this tests that the plastic centroid takes into account the # correct "center" of the original section which is affected by EA of each # of the constituent geometries. steel = Material( name="Steel", elastic_modulus=200e3, poissons_ratio=0.3, density=7.85e-6, yield_strength=500, color="grey", ) timber = Material( name="Timber", elastic_modulus=5e3, poissons_ratio=0.35, density=6.5e-7, yield_strength=20, color="burlywood", ) # create 310UB40.4 ub = i_section(d=304, b=165, t_f=10.2, t_w=6.1, r=11.4, n_r=8, material=steel) # create timber panel on top of the UB panel = rectangular_section(d=50, b=600, material=timber) panel = panel.align_center(ub).align_to(ub, on="top") # merge the two sections into one geometry object geometry = CompoundGeometry([ub, panel]) # create a mesh - use a mesh size of 5 for the UB, 20 for the panel geometry.create_mesh(mesh_sizes=[100, 100]) # create a Section object section = Section(geometry) # perform a geometric, warping and plastic analysis section.calculate_geometric_properties() section.calculate_plastic_properties() x_pc, y_pc = section.get_pc() assert x_pc == pytest.approx(82.5) assert y_pc == pytest.approx(250.360654576)
def test_compound_rectangular_perimeter(): rect1 = sections.rectangular_section(d=100, b=100) rect2 = sections.rectangular_section(d=50, b=50).align_to(rect1, on="top") rect3 = sections.rectangular_section(d=50, b=100).align_to(rect1, on="right") rect4 = (sections.rectangular_section(d=50, b=50).align_to( rect3, on="bottom").align_to(rect3, on="right", inner=True)) geom = rect1 + rect2 + rect3 + rect4 geom.create_mesh([100]) section = Section(geom) section.calculate_geometric_properties() assert section.get_perimeter() == (150 + 50 + 50 + 100 + 100 + 50 + 50 + 50 + 50 + 150)
def test_i_section(): i_section = steel_sections.i_section(d=308, b=305, t_f=15.4, t_w=9.9, r=16.5, n_r=16) i_section.create_mesh([100]) section = Section(i_section) section.calculate_geometric_properties() perim = ((2 * 305) + (4 * 15.4) + 2 * (305 - 9.9 - 2 * 16.5) + (2 * np.pi * 16.5) + 2 * (308 - 2 * 15.4 - 2 * 16.5)) check.almost_equal(section.get_perimeter(), perim, rel=r_tol)
def test_compound_rectangular_isection_perimeter2(): i_section = steel_sections.i_section(d=308, b=305, t_f=15.4, t_w=9.9, r=16.5, n_r=16) rect1 = (sections.rectangular_section( d=330, b=16).align_center(i_section).align_to(i_section, "left")) rect2 = (sections.rectangular_section( d=330, b=16).align_center(i_section).align_to(i_section, "right")) geom = i_section + rect1 + rect2 geom.create_mesh([100]) section = Section(geom) section.calculate_geometric_properties() assert section.get_perimeter( ) == 2 * 330 + 4 * 16 + 2 * 305 + 2 * (330 - 308)
def test_compound_rectangular_isection_perimeter1(): d = 300 b = 150 tf = 10 tw = 6 r = 12 b_p = 250 t_p = 16 ub = steel_sections.i_section(d=d, b=b, t_f=tf, t_w=tw, r=r, n_r=16) plate = (sections.rectangular_section( b=b_p, d=t_p).align_center(ub).align_to(ub, on="top")) geom = ub + plate geom.create_mesh([100]) section = Section(geom) section.calculate_geometric_properties() perim = (b + (4 * tf) + 2 * (b - tw - 2 * r) + (2 * np.pi * r) + 2 * (d - 2 * tf - 2 * r) + (b_p - b) + (2 * t_p) + b_p) check.almost_equal(section.get_perimeter(), perim, rel=r_tol)
def test_rectangular_offset(): # exterior negative offset rect = sections.rectangular_section(d=500, b=300) rect = rect.offset_perimeter(amount=-10, where="exterior") rect.create_mesh([200]) section = Section(rect) section.calculate_geometric_properties() area = 480 * 280 check.almost_equal(section.get_area(), area, rel=r_tol) # exterior positive offset rect = sections.rectangular_section(d=500, b=300) rect = rect.offset_perimeter(amount=10, where="exterior") rect.create_mesh([200]) section = Section(rect) section.calculate_geometric_properties() area = 520 * 320 - (20 * 20 - np.pi * 10 * 10) check.almost_equal(section.get_area(), area, rel=r_tol)
def test_compound_rectangular_isection_offset_corrode(): d = 300 b = 150 tf = 10 tw = 8 r = 12 b_p = 250 t_p = 16 ub = steel_sections.i_section(d=d, b=b, t_f=tf, t_w=tw, r=r, n_r=16) plate = (sections.rectangular_section( b=b_p, d=t_p).align_center(ub).align_to(ub, on="top")) geom_test = ub + plate geom_test = geom_test.offset_perimeter(amount=-2, where="exterior") geom_test.create_mesh([100]) section_test = Section(geom_test) section_test.calculate_geometric_properties() ub_corroded = steel_sections.mono_i_section(d=298, b_t=146, b_b=146, t_ft=8, t_fb=6, t_w=4, r=14, n_r=16) plate_corroded1 = (sections.rectangular_section( b=146, d=2).align_center(ub_corroded).align_to(ub_corroded, "top")) plate_corroded2 = (sections.rectangular_section( b=246, d=12).align_center(ub_corroded).align_to(plate_corroded1, "top")) rad_l = (draw_radius(2, 8).align_to(plate_corroded1, "left").align_to(plate_corroded2, "bottom")) rad_r = (draw_radius(2, 8).mirror_section("y", [2, 0]).align_to( plate_corroded1, "right").align_to(plate_corroded2, "bottom")) geom_corroded = ub_corroded + plate_corroded1 + plate_corroded2 + rad_l + rad_r geom_corroded.create_mesh([100]) section_corroded = Section(geom_corroded) section_corroded.calculate_geometric_properties() check.almost_equal(section_test.get_area(), section_corroded.get_area(), rel=r_tol)
def PeeryEx6_2_1(): """ Example 1 in Sec. 6.2 (Symmetric Bending) This is a symmetric I-section with no lateral supports, undergoing pure unidirectional cantilever bending. Note that units here are **inches**, to match the text. """ name = "Peery_6.2.1" geom = nastran_sections.nastran_i(6, 3, 3, 1, 1, 1) geom = geom.shift_section(0, -3) geom = geom.create_mesh([0.25]) xsect = Section(geom) xsect.calculate_geometric_properties() # This plotting code was just for verifying the section offsets. # ax = xsect.plot_centroids(pause=False, render=False) # ax.grid(1, which='both', linestyle=':') # fig = ax.get_figure() # fig.savefig(f'{name}_geom.png') return geom, xsect
def test_compound_rhs_isection_perimeter(): d = 200 b = 150 t = 9 r = 15 b_p = 250 t_p = 16 rhs = steel_sections.rectangular_hollow_section(d=d, b=b, t=t, r_out=r, n_r=16) plate1 = (sections.rectangular_section( b=b_p, d=t_p).align_center(rhs).align_to(rhs, on="top")) plate2 = (sections.rectangular_section( b=b_p, d=t_p).align_center(rhs).align_to(rhs, on="bottom")) geom = rhs + plate1 + plate2 geom.create_mesh([100]) section = Section(geom) section.calculate_geometric_properties() perim = ((2 * b_p) + (4 * t_p) + 2 * (b_p - b + 2 * r) + (2 * np.pi * r) + 2 * (d - 2 * r)) check.almost_equal(section.get_perimeter(), perim, rel=r_tol)
def test_rectangle(): fy = 500 E = 200e3 b = 50 d = 100 steel = Material( name="Steel", elastic_modulus=E, poissons_ratio=0.3, yield_strength=fy, density=8.05e-6, color="grey", ) Sx = b * d * d / 4 Mp = Sx * fy geom_mat = sections.rectangular_section(d=d, b=b, material=steel) geom_nomat = sections.rectangular_section(d=d, b=b) geom_mat.create_mesh(mesh_sizes=[2.5]) geom_nomat.create_mesh(mesh_sizes=[2.5]) sec_mat = Section(geom_mat) sec_nomat = Section(geom_nomat) sec_mat.calculate_geometric_properties() sec_mat.calculate_plastic_properties() sec_nomat.calculate_geometric_properties() sec_nomat.calculate_plastic_properties() assert sec_nomat.get_s()[0] == pytest.approx(Sx) assert sec_mat.get_s()[0] == pytest.approx(Mp) assert sec_mat.get_s()[0] / fy == sec_nomat.get_s()[0]
def test_rectangular_perimeter(): rect = sections.rectangular_section(d=500, b=300) rect.create_mesh([200]) section = Section(rect) section.calculate_geometric_properties() assert section.get_perimeter() == 2 * (500 + 300)
def test_multi_nested_compound_geometry_from_points(): """ Testing a multi-nested section. This section contains three nested materials in concentric square rings with a hole going through the center of the whole section. This test confirms that the section can be successfully built using .from_points, that the control_points and hole nodes persist in the right locations, and that the plastic section calculation raises a warning because the nested regions overlap. """ points = [ [-50.0, 50.0], [50.0, 50.0], [50.0, -50.0], [-50.0, -50.0], [37.5, -37.5], [37.5, 37.5], [-37.5, 37.5], [-37.5, -37.5], [25.0, -25.0], [25.0, 25.0], [-25.0, 25.0], [-25.0, -25.0], [12.5, -12.5], [12.5, 12.5], [-12.5, 12.5], [-12.5, -12.5], ] facets = [ [0, 1], [1, 2], [2, 3], [3, 0], [4, 5], [5, 6], [6, 7], [7, 4], [8, 9], [9, 10], [10, 11], [11, 8], [12, 13], [13, 14], [14, 15], [15, 12], ] control_points = [[-43.75, 0.0], [-31.25, 0.0], [-18.75, 0.0]] holes = [[0, 0]] mat1 = Material( name="mat1", elastic_modulus=2, poissons_ratio=0.3, density=1e-6, yield_strength=5, color="grey", ) mat2 = Material( name="mat2", elastic_modulus=5, poissons_ratio=0.2, density=2e-6, yield_strength=10, color="blue", ) mat3 = Material( name="mat3", elastic_modulus=1, poissons_ratio=0.25, density=1.5e-6, yield_strength=3, color="green", ) materials = [mat1, mat2, mat3] nested_compound = CompoundGeometry.from_points( points=points, facets=facets, control_points=control_points, holes=holes, materials=materials, ) wkt_test_geom = shapely.wkt.loads( "MULTIPOLYGON (((50 50, 50 -50, -50 -50, -50 50, 50 50), (12.5 12.5, -12.5 12.5, -12.5 -12.5, 12.5 -12.5, 12.5 12.5)), ((-37.5 -37.5, -37.5 37.5, 37.5 37.5, 37.5 -37.5, -37.5 -37.5), (12.5 12.5, -12.5 12.5, -12.5 -12.5, 12.5 -12.5, 12.5 12.5)), ((-25 -25, -25 25, 25 25, 25 -25, -25 -25), (12.5 12.5, -12.5 12.5, -12.5 -12.5, 12.5 -12.5, 12.5 12.5)))" ) assert (nested_compound.geom - wkt_test_geom) == Polygon() assert nested_compound.control_points == [ (-43.75, 0.0), (-31.25, 0.0), (-18.75, 0.0), ] assert nested_compound.holes == [(0, 0)] # test materials for idx, geom in enumerate(nested_compound.geoms): assert geom.material == materials[idx] # Section contains overlapping geometries which will result in potentially incorrect # plastic properties calculation (depends on user intent and geometry). # Test to ensure a warning is raised about this to notify the user. nested_compound.create_mesh([25, 30, 35]) nested_compound_sec = Section(nested_compound) nested_compound_sec.calculate_geometric_properties() with pytest.warns(UserWarning): nested_compound_sec.calculate_plastic_properties()
box, ) from shapely import wkt import json big_sq = rectangular_section(d=300, b=250) small_sq = rectangular_section(d=100, b=75) small_hole = rectangular_section(d=40, b=30).align_center(small_sq) i_sec = i_section(d=200, b=100, t_f=20, t_w=10, r=12, n_r=12) small_sq_w_hole = small_sq - small_hole composite = (big_sq + small_sq_w_hole.align_to( big_sq, on="top", inner=True).align_to(big_sq, on="top") + i_sec.align_to( big_sq, on="bottom", inner=True).align_to(big_sq, on="right")) composite.create_mesh([200]) comp_sec = Section(composite) comp_sec.calculate_geometric_properties() comp_sec.calculate_plastic_properties() # Subtractive modelling nested_geom = (small_sq - small_hole) + small_hole nested_geom.create_mesh([50]) nested_sec = Section(nested_geom) # Overlapped modelling overlay_geom = small_sq + small_hole overlay_geom.create_mesh([50]) overlay_sec = Section(overlay_geom) steel = Material("steel", 200e3, 0.3, 7.85e-6, 400, "grey")
# %% # Loop through all the widths for b in b_list: # calculate d assuming area = 1 d = 1 / b d_list.append(d) # compute mesh size ms = d * b / n # perform a warping analysis on rectangle geometry = sections.rectangular_section(d=d, b=b) geometry.create_mesh(mesh_sizes=[ms]) section = Section(geometry) section.calculate_geometric_properties() section.calculate_warping_properties() # get the torsion constant j = section.get_j() print("d/b = {0:.3f}; J = {1:.5e}".format(d / b, j)) j_list.append(j) # %% # Plot the torsion constant as a function of the aspect ratio (fig, ax) = plt.subplots() ax.plot(np.array(d_list) / b_list, j_list, "kx-") ax.set_xlabel("Aspect Ratio [d/b]") ax.set_ylabel("Torsion Constant [J]") ax.set_title("Rectangular Section Torsion Constant") plt.show()
def test_box_offset(): # exterior negative offset box = steel_sections.rectangular_hollow_section(d=200, b=100, t=10, r_out=0, n_r=1) box = box.offset_perimeter(amount=-5, where="exterior") box.create_mesh([50]) section = Section(box) section.calculate_geometric_properties() area = 190 * 90 - 180 * 80 check.almost_equal(section.get_area(), area, rel=r_tol) # exterior positve offset box = steel_sections.rectangular_hollow_section(d=200, b=100, t=10, r_out=0, n_r=1) box = box.offset_perimeter(amount=5, where="exterior") box.create_mesh([50]) section = Section(box) section.calculate_geometric_properties() area = 210 * 110 - (10 * 10 - np.pi * 5 * 5) - 180 * 80 check.almost_equal(section.get_area(), area, rel=r_tol) # interior negative offset box = steel_sections.rectangular_hollow_section(d=200, b=100, t=10, r_out=0, n_r=1) box = box.offset_perimeter(amount=-5, where="interior") box.create_mesh([50]) section = Section(box) section.calculate_geometric_properties() area = 200 * 100 - 170 * 70 check.almost_equal(section.get_area(), area, rel=r_tol) # interior positive offset box = steel_sections.rectangular_hollow_section(d=200, b=100, t=10, r_out=0, n_r=1) box = box.offset_perimeter(amount=5, where="interior") box.create_mesh([50]) section = Section(box) section.calculate_geometric_properties() area = 200 * 100 - 190 * 90 + (10 * 10 - np.pi * 5 * 5) check.almost_equal(section.get_area(), area, rel=r_tol) # all negative offset box = steel_sections.rectangular_hollow_section(d=200, b=100, t=10, r_out=0, n_r=1) box = box.offset_perimeter(amount=-2.5, where="all") box.create_mesh([50]) section = Section(box) section.calculate_geometric_properties() area = 195 * 95 - 185 * 85 + (5 * 5 - np.pi * 2.5 * 2.5) check.almost_equal(section.get_area(), area, rel=r_tol) # all positive offset box = steel_sections.rectangular_hollow_section(d=200, b=100, t=10, r_out=0, n_r=1) box = box.offset_perimeter(amount=5, where="all") box.create_mesh([50]) section = Section(box) section.calculate_geometric_properties() area = 210 * 110 - (10 * 10 - np.pi * 5 * 5) - 170 * 70 check.almost_equal(section.get_area(), area, rel=r_tol)
import pytest_check as check from shapely.geometry import Polygon from sectionproperties.pre.geometry import Geometry import sectionproperties.pre.library.primitive_sections as sections import sectionproperties.pre.library.steel_sections as steel_sections from sectionproperties.analysis.section import Section from sectionproperties.tests.helper_functions import validate_properties # Setup for angle section angle = steel_sections.angle_section(d=150, b=90, t=12, r_r=10, r_t=5, n_r=8) angle.create_mesh(mesh_sizes=2.5) angle_section = Section(angle) angle_section.calculate_geometric_properties() angle_section.calculate_plastic_properties() angle_section.calculate_warping_properties() def test_angle_all_properties(): check.almost_equal(angle_section.section_props.area, 2747.059) check.almost_equal(angle_section.section_props.perimeter, 471.3501) check.almost_equal(angle_section.section_props.cx, 2.122282e1) check.almost_equal(angle_section.section_props.cy, 5.098127e1) check.almost_equal(angle_section.section_props.ixx_g, 1.342632e7) check.almost_equal(angle_section.section_props.iyy_g, 2.955753e6) check.almost_equal(angle_section.section_props.ixy_g, 1.086603e6) check.almost_equal(angle_section.section_props.ixx_c, 6.286470e6) check.almost_equal(angle_section.section_props.iyy_c, 1.718455e6) check.almost_equal(angle_section.section_props.ixy_c, -1.885622e6) check.almost_equal(angle_section.section_props.zxx_plus, 6.348769e4) check.almost_equal(angle_section.section_props.zxx_minus, 1.233094e5)
import pytest_check as check # import unittest import sectionproperties.pre.library.primitive_sections as primitive_sections import sectionproperties.pre.pre as pre from sectionproperties.analysis.section import Section from sectionproperties.tests.helper_functions import validate_properties import sectionproperties.analysis.section as file # Rectangle section setup rectangle_geometry = primitive_sections.rectangular_section(b=50, d=100) rectangle_geometry.create_mesh(mesh_sizes=100) rectangle_section = Section(rectangle_geometry) rectangle_section.calculate_geometric_properties() rectangle_section.calculate_warping_properties() rectangle_section.calculate_plastic_properties() tol = 1e-6 warp_tol = 1e-4 def test_rectangular_section_geometric(): check.almost_equal(rectangle_section.section_props.area, 100 * 50, rel=tol) check.almost_equal(rectangle_section.section_props.perimeter, 2 * 100 + 2 * 50, rel=tol) check.almost_equal(rectangle_section.section_props.mass, 1 * 100 * 50, rel=tol) check.almost_equal(rectangle_section.section_props.ea,