"""Euler-Bernoulli beam solvers with exact closed-form solutions. Six configurations covering common support and loading combinations: - Simply supported + point load / UDL - Cantilever + point load / UDL - Fixed-fixed + point load / UDL Assumptions (Euler-Bernoulli theory): - Plane sections remain plane after deformation - Small deflections (linear elasticity) - Homogeneous, isotropic material - Rectangular cross-section Reference: Timoshenko, S.P. & Gere, J.M., "Mechanics of Materials" """ from typing import Any from src.data.schema import SolutionResult from src.data.solvers.base import AnalyticalSolver class SimplySupported_PointLoad(AnalyticalSolver): """Simply supported beam with central point load P. delta_max = PL^3 / (48EI) at midspan sigma_max = PL / (4S) at midspan (max bending moment M = PL/4) """ @property def config_id(self) -> str: return "beam_ss_point" @property def problem_family(self) -> str: return "beam" def solve(self, params: dict[str, Any]) -> SolutionResult: L = params["length"] b = params["width"] h = params["height"] E = params["elastic_modulus"] sigma_y = params["yield_strength"] P = params["point_load"] I = b * h**3 / 12.0 # noqa: E741 S = b * h**2 / 6.0 max_deflection = P * L**3 / (48.0 * E * I) max_stress = P * L / (4.0 * S) return SolutionResult.from_stress(max_stress, max_deflection, sigma_y) class SimplySupported_UDL(AnalyticalSolver): """Simply supported beam with uniform distributed load w. delta_max = 5wL^4 / (384EI) at midspan sigma_max = wL^2 / (8S) at midspan (max bending moment M = wL^2/8) """ @property def config_id(self) -> str: return "beam_ss_udl" @property def problem_family(self) -> str: return "beam" def solve(self, params: dict[str, Any]) -> SolutionResult: L = params["length"] b = params["width"] h = params["height"] E = params["elastic_modulus"] sigma_y = params["yield_strength"] w = params["distributed_load"] I = b * h**3 / 12.0 # noqa: E741 S = b * h**2 / 6.0 max_deflection = 5.0 * w * L**4 / (384.0 * E * I) max_stress = w * L**2 / (8.0 * S) return SolutionResult.from_stress(max_stress, max_deflection, sigma_y) class Cantilever_PointLoad(AnalyticalSolver): """Cantilever beam with tip point load P. delta_max = PL^3 / (3EI) at free end sigma_max = PL / S at fixed end (max bending moment M = PL) """ @property def config_id(self) -> str: return "beam_cantilever_point" @property def problem_family(self) -> str: return "beam" def solve(self, params: dict[str, Any]) -> SolutionResult: L = params["length"] b = params["width"] h = params["height"] E = params["elastic_modulus"] sigma_y = params["yield_strength"] P = params["point_load"] I = b * h**3 / 12.0 # noqa: E741 S = b * h**2 / 6.0 max_deflection = P * L**3 / (3.0 * E * I) max_stress = P * L / S return SolutionResult.from_stress(max_stress, max_deflection, sigma_y) class Cantilever_UDL(AnalyticalSolver): """Cantilever beam with uniform distributed load w. delta_max = wL^4 / (8EI) at free end sigma_max = wL^2 / (2S) at fixed end (max bending moment M = wL^2/2) """ @property def config_id(self) -> str: return "beam_cantilever_udl" @property def problem_family(self) -> str: return "beam" def solve(self, params: dict[str, Any]) -> SolutionResult: L = params["length"] b = params["width"] h = params["height"] E = params["elastic_modulus"] sigma_y = params["yield_strength"] w = params["distributed_load"] I = b * h**3 / 12.0 # noqa: E741 S = b * h**2 / 6.0 max_deflection = w * L**4 / (8.0 * E * I) max_stress = w * L**2 / (2.0 * S) return SolutionResult.from_stress(max_stress, max_deflection, sigma_y) class FixedFixed_PointLoad(AnalyticalSolver): """Fixed-fixed beam with central point load P. delta_max = PL^3 / (192EI) at midspan sigma_max = PL / (8S) at fixed ends (max bending moment M = PL/8) """ @property def config_id(self) -> str: return "beam_fixed_point" @property def problem_family(self) -> str: return "beam" def solve(self, params: dict[str, Any]) -> SolutionResult: L = params["length"] b = params["width"] h = params["height"] E = params["elastic_modulus"] sigma_y = params["yield_strength"] P = params["point_load"] I = b * h**3 / 12.0 # noqa: E741 S = b * h**2 / 6.0 max_deflection = P * L**3 / (192.0 * E * I) max_stress = P * L / (8.0 * S) return SolutionResult.from_stress(max_stress, max_deflection, sigma_y) class FixedFixed_UDL(AnalyticalSolver): """Fixed-fixed beam with uniform distributed load w. delta_max = wL^4 / (384EI) at midspan sigma_max = wL^2 / (12S) at fixed ends (max bending moment M = wL^2/12) """ @property def config_id(self) -> str: return "beam_fixed_udl" @property def problem_family(self) -> str: return "beam" def solve(self, params: dict[str, Any]) -> SolutionResult: L = params["length"] b = params["width"] h = params["height"] E = params["elastic_modulus"] sigma_y = params["yield_strength"] w = params["distributed_load"] I = b * h**3 / 12.0 # noqa: E741 S = b * h**2 / 6.0 max_deflection = w * L**4 / (384.0 * E * I) max_stress = w * L**2 / (12.0 * S) return SolutionResult.from_stress(max_stress, max_deflection, sigma_y) # Registry of all beam solvers BEAM_SOLVERS: dict[str, type[AnalyticalSolver]] = { "beam_ss_point": SimplySupported_PointLoad, "beam_ss_udl": SimplySupported_UDL, "beam_cantilever_point": Cantilever_PointLoad, "beam_cantilever_udl": Cantilever_UDL, "beam_fixed_point": FixedFixed_PointLoad, "beam_fixed_udl": FixedFixed_UDL, }