def test_deflection_for_fixed_cantilevered_beam_with_load_at_any_point(): P = -1000 # load in lbs down a = 7 # position of load in inches L = 25 # length of beam in inches E = 29e6 # Young's modulus in psi Ixx = 345 # area moment of inertia in in**4 b = L - a # function to calculate deflection anywhere along the length of the beam d1 = lambda x: P * b**2 / (6 * E * Ixx) * (3 * L - 3 * x - b) # x < a d2 = lambda x: P * (L - x)**2 / (6 * E * Ixx) * (3 * b - L + x) # x > a d3 = lambda x: P * b**3 / (3 * E * Ixx) # x == a beam = Beam(L, [PointLoad(P, a)], [FixedReaction(L)], E, Ixx) for x in [0, 7, 12.5, 25]: # check the deflection of the beam at both end points, and the center if x < a: exact = d1(x) elif x > a: exact = d2(x) else: exact = d3(x) assert pytest.approx(beam.deflection(x), rel=1e-12) == exact, \ f"Calculated deflection does not match expected deflection at {x}"
def test_reaction_types(): pr = PinnedReaction(0) fr = FixedReaction(0) assert pr.boundary == ( 0, None), "PinnedReaction only has one degree of freedom" assert fr.boundary == ( 0, 0), "FixedReaction does not have any degrees of freedom"
def test_stiffness_matrix_k(): beam = Beam(25, [PointLoad(-100, 25)], [FixedReaction(0)], 29e6, 345) assert beam.K.shape == (4, 4), "stiffness matrix is not expected size" # add another point load and verify the stiffness matrix changes size # accordingly beam.loads.append(PointLoad(-500, 12)) beam.remesh() assert beam.K.shape == (6, 6), "stiffness matrix size did not update"
def test_node_deflections_at_free_end(): for load in [PointLoad(-100, 25), MomentLoad(-100, 25)]: beam = Beam(25, [load], [FixedReaction(0)], 29e6, 345) # check that the deflection at the free end is non-zero and negative msgs = [ "displacement at free end is not negative", "angular displacement at free end is not negative", ] for i, msg in enumerate(msgs, 2): assert beam.node_deflections[i][0] < 0, msg
def test_node_deflections_at_fixed_end(): for load in [PointLoad(-100, 25), MomentLoad(-100, 25)]: beam = Beam(25, [load], [FixedReaction(0)], 29e6, 345) # check that the deflection at the fixed end is 0 msgs = [ "displacement at fixed end is non-zero", "angular displacement at fixed end is non-zero", ] for i, msg in enumerate(msgs): assert beam.node_deflections[i][0] == 0, msg
def test_plot_default_labels(): b = Beam(10, [PointLoad(10, 10)], [FixedReaction(0)]) fig, axes = b.plot() x_labels = ("", "", "Beam position, x") y_labels = ("shear", "moment", "deflection") assert len(axes) == len(x_labels), "wrong number of sub-plots" for ax, x_label, y_label in zip(axes, x_labels, y_labels): assert ax.get_xlabel() == x_label assert ax.get_ylabel() == y_label
def test_invalid_deflection_location(): beam = Beam(25, [PointLoad(-100, 25)], [FixedReaction(0)], 29e6, 345) with pytest.raises(ValueError): beam.deflection(-4) # a value less than 0 with pytest.raises(ValueError): beam.deflection(beam.length + 5) # a value greater then the length with pytest.raises(TypeError): beam.deflection('a string (not a number)')
def test_plot_custom_labels(): b = Beam(10, [PointLoad(10, 10)], [FixedReaction(0)]) diagrams = ("deflection", "deflection", "moment", "shear") labels = ("def1", "def2", "M", "V") fig, axes = b.plot(diagrams=diagrams, diagram_labels=labels) assert len(axes) == len(diagrams), "wrong number of sub-plots" x_labels = ["" for _ in range(len(diagrams) - 1)] x_labels.append("Beam position, x") for ax, x_label, y_label in zip(axes, x_labels, labels): assert ax.get_xlabel() == x_label assert ax.get_ylabel() == y_label
def test_solve_method(): beam = Beam(25, [PointLoad(-100, 25)], [FixedReaction(0)], 29e6, 345) reaction = beam.reactions[0] assert reaction.force is None, "Reaction force was not None before being solved" assert reaction.moment is None, "Reaction moment was not None before being solved" beam.solve() reaction = beam.reactions[0] assert reaction.force == 100, "Reaction force must be equal to and opposite load" assert ( reaction.moment == 100 * 25), "Reaction moment must be equal to the load times the moment arm"
def test_apply_boundary_conditions(): beam = Beam(25, [PointLoad(-100, 25), PointLoad(-100, 12)], [FixedReaction(0)], 29e6, 345) k = beam.K bcs = [(None, None), (0, 0)] initial_shape = beam.K.shape assert initial_shape == ( 6, 6), "stiffness matrix does not match expected size" ki = beam.apply_boundary_conditions(k, bcs) final_shape = ki.shape assert initial_shape == final_shape, ("stiffness matrix changed shape " "when applying boundary conditions")
def test_shear(): beam = Beam(25, [PointLoad(-1000, 25)], [FixedReaction(0)]) for x in [0.5, 5, 13, 20, 24.5]: assert pytest.approx(beam.shear(x), rel=1e-5) == 1000, \ f"shear does not equal load at location {x}" # right now, the derivative function will try to calculate shear outside # of the beam when calculating shear at or near endpoints. Verify that # calculating shear at ends raises a ValueError. It should also raise a # ValueError when the input is outside the beam for x in [-5, 0, 25, 35]: with pytest.raises(ValueError): beam.shear(x)
def test_moment_for_fixed_cantilevered_beam_with_load_at_end(): P = -1000 # load in lbs down L = 25 # length of beam in inches E = 29e6 # Young's modulus in psi Ixx = 345 # area moment of inertia in in**4 # function to calculate moment anywhere along the length of the beam m = lambda x: P * x beam = Beam(L, [PointLoad(P, 0)], [FixedReaction(L)], E, Ixx) for x in [7, 12.5, 25]: # check the deflection of the beam at both end points, and the center assert pytest.approx(beam.moment(x), rel=0.01) == m(x), \ f"Calculated moment does not match expected moment at {x}" with pytest.warns(UserWarning): beam.moment(0)
def example_1(): """ Cantilevered Beam with Fixed Support and End Loading """ print("=" * 79) print("Example 1") print( "Show an example with a cantilevered beam with a fixed support and " "point load at the end\n" ) beam_len = 10 # Note that both the reaction and load are both lists. They must always be # given to Beam as a list, r = [FixedReaction(0)] # define reactions as list p = [PointLoad(magnitude=-2, location=beam_len)] # define loads as list b = Beam(beam_len, loads=p, reactions=r, E=29e6, Ixx=125) # an explicit solve is required to calculate the reaction values b.solve() print(b)
def test_cantilevered_beam_load_at_end(): """fixed beam with concentrated load at free end case 13 """ R = -P M_max = P * L # at fixed end d_max = P * L**3 / (3 * EI) # at free end beam = Beam( length=L, loads=[PointLoad(magnitude=P, location=0)], reactions=[FixedReaction(L)], E=E, Ixx=Ixx, ) beam.solve() validate(beam, loc=0, R=[(R, M_max)], M_loc=0, d_loc=d_max) assert pytest.approx(beam.moment(L), rel=TOL) == M_max
def test_invalid_load_placement(): reactions = [PinnedReaction(x) for x in [0, 50, 100]] loads = [PointLoad(-100, x) for x in [0, 50, 100]] # there should be a warning indicating that the load position was moved # slightly so it does not line up with the reaction. with pytest.warns(UserWarning): beam = Beam(100, loads=loads, reactions=reactions) for load, reaction in zip(beam.loads, beam.reactions): assert (load.location != reaction.location ), "moved load is still the same as a reaction" @pytest.mark.parametrize("invalid_load", ["a string", FixedReaction(0), [], 10]) def test_invalid_load_errors(invalid_load): # Check for a TypeError for a variety of invalid loads with pytest.raises(TypeError): Beam(25, loads=[invalid_load], reactions=[FixedReaction(0)]) @pytest.mark.parametrize("invalid_reaction", ["a string", PointLoad(25, 15), [], 10]) def test_invalid_reaction_errors(invalid_reaction): # Check for an TypeError for a variety of invalid reactions with pytest.raises(TypeError): Beam(25, loads=[PointLoad(-100, 15)], reactions=[invalid_reaction]) def test_shape_function():
def beam_fixed(length): yield Beam(length=length, loads=[PointLoad(-100, length)], reactions=[FixedReaction(0)])
def reaction_fixed(): """common fixed reaction at 0""" yield [FixedReaction(0)]
def test_bending_stress_depreciation_warning(): with pytest.warns(DeprecationWarning): b = Beam(10, [PointLoad(10, 10)], [FixedReaction(0)]) b.bending_stress(x=5, c=1)
def test_invalid_load_errors(): # Check for a TypeError for a variety of invalid loads for invalid_load in ['a string', FixedReaction(0), [], 10]: with pytest.raises(TypeError): Beam(25, loads=[invalid_load], reactions=[FixedReaction(0)])
def test_plot_one_diagram(): b = Beam(10, [PointLoad(10, 10)], [FixedReaction(0)]) fig, axes = b.plot(diagrams=("deflection", )) assert len(axes) == 1, "expected length of axes was 1" for ax, y_label in zip(axes, ("deflection", )): assert ax.get_ylabel() == y_label
import pytest from femethods.loads import PointLoad from femethods.mesh import Mesh from femethods.reactions import FixedReaction LOADS = [PointLoad(magnitude=-1000, location=15)] REACTIONS = [FixedReaction(0)] LENGTH = 25 @pytest.fixture def mesh(): return Mesh(LENGTH, LOADS, REACTIONS, dof=2) def test_mesh_properties(mesh): # there should be a node at the start and end of the beam, as well as a # node for any loads assert mesh.nodes == [0, 15, 25], "Mesh nodes do not match expected" assert mesh.dof == 6, "Wrong number of global degrees-of-freedom" assert mesh.lengths == [15, 10], "Mesh elements do not have expected lengths" assert mesh.num_elements == 2, "Mesh element count does not match" assert mesh.num_elements == len(mesh.lengths) with pytest.raises(AttributeError): mesh.nodes = "Mesh nodes property is read-only" with pytest.raises(AttributeError): mesh.dof = "Mesh dof should be read-only" with pytest.raises(AttributeError):
def test_plot_diagram_labels_without_diagrams(): with pytest.raises(ValueError): b = Beam(10, [PointLoad(10, 10)], [FixedReaction(0)]) b.plot(diagram_labels=("V, lb", "M, in/lb", "delta, in"))
def test_plot_diagrams_diagrams_label_mismatch(): with pytest.raises(ValueError): b = Beam(10, [PointLoad(10, 10)], [FixedReaction(0)]) b.plot(diagrams=("shear", ), diagram_labels=("shear", "moment"))
def test_plot_diagrams_invalid_value(): with pytest.raises(ValueError): b = Beam(10, [PointLoad(10, 10)], [FixedReaction(0)]) b.plot(diagrams=("shear", "bad value"))
def test_invalid_load_errors(invalid_load): # Check for a TypeError for a variety of invalid loads with pytest.raises(TypeError): Beam(25, loads=[invalid_load], reactions=[FixedReaction(0)])
def test_shape_of_node_deflections(): beam = Beam(25, [PointLoad(-100, 25)], [FixedReaction(0)], 29e6, 345) assert beam.node_deflections.shape == (4, 1), \ "nodal deflections shape is not expected"