calculate_beam_reactions
Calculate reaction forces at supports of a simply supported beam under point loads. Solves moment equilibrium to output left and right reactions, total load, and balance check.
Instructions
Calculate reaction forces for a simply supported beam.
Uses moment equilibrium about supports to find reaction forces.
Args:
beam_length: Beam length in meters
loads: Point loads in Newtons (downward positive) (or JSON string)
load_positions: Positions of loads from left end in meters (or JSON string)
Returns:
Dict containing:
- reaction_left: Reaction force at left support in Newtons
- reaction_right: Reaction force at right support in Newtons
- total_load: Total downward load in Newtons
- is_balanced: Whether reactions balance loads
Example - Beam with two loads:
result = await calculate_beam_reactions(
beam_length=10.0,
loads=[1000, 500],
load_positions=[3.0, 7.0]
)Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| beam_length | Yes | ||
| loads | Yes | ||
| load_positions | Yes |
Implementation Reference
- MCP tool handler for calculate_beam_reactions - async function decorated with @tool. Parses JSON string inputs, creates a BeamReactionRequest, calls the core calculation function, and returns the response dict.
@tool # type: ignore[arg-type] async def calculate_beam_reactions( beam_length: float, loads: list[float] | str, load_positions: list[float] | str, ) -> dict: """Calculate reaction forces for a simply supported beam. Uses moment equilibrium about supports to find reaction forces. Args: beam_length: Beam length in meters loads: Point loads in Newtons (downward positive) (or JSON string) load_positions: Positions of loads from left end in meters (or JSON string) Returns: Dict containing: - reaction_left: Reaction force at left support in Newtons - reaction_right: Reaction force at right support in Newtons - total_load: Total downward load in Newtons - is_balanced: Whether reactions balance loads Example - Beam with two loads: result = await calculate_beam_reactions( beam_length=10.0, loads=[1000, 500], load_positions=[3.0, 7.0] ) """ from ..statics import BeamReactionRequest from ..statics import calculate_beam_reactions as calc_beam if isinstance(loads, str): loads = json.loads(loads) if isinstance(load_positions, str): load_positions = json.loads(load_positions) request = BeamReactionRequest( beam_length=beam_length, loads=loads, load_positions=load_positions, ) response = calc_beam(request) return response.model_dump() - src/chuk_mcp_physics/statics.py:403-445 (handler)Core calculation function for beam reactions - uses moment equilibrium about left support (ΣM_left=0) to find reaction_right, then force equilibrium (ΣF_y=0) to find reaction_left. Validates load positions are within beam length.
def calculate_beam_reactions(request: BeamReactionRequest) -> BeamReactionResponse: """Calculate reaction forces for a simply supported beam with point loads. Uses moment equilibrium about left support: Σ M_left = 0: R_right × L - Σ(P_i × x_i) = 0 Then force equilibrium: Σ F_y = 0: R_left + R_right - Σ P_i = 0 Args: request: Beam reaction request Returns: Reaction forces at supports """ if len(request.loads) != len(request.load_positions): raise ValueError("Number of loads must equal number of positions") # Check that all positions are within beam length for pos in request.load_positions: if pos < 0 or pos > request.beam_length: raise ValueError(f"Load position {pos}m is outside beam length {request.beam_length}m") total_load = sum(request.loads) # Moment about left support moment_about_left = sum(load * pos for load, pos in zip(request.loads, request.load_positions)) # R_right from moment equilibrium reaction_right = moment_about_left / request.beam_length # R_left from force equilibrium reaction_left = total_load - reaction_right # Check if balanced is_balanced = abs((reaction_left + reaction_right) - total_load) < 0.01 return BeamReactionResponse( reaction_left=reaction_left, reaction_right=reaction_right, total_load=total_load, is_balanced=is_balanced, ) - BeamReactionRequest Pydantic model - input schema with beam_length (float, >0), loads (list of floats), and load_positions (list of floats).
class BeamReactionRequest(BaseModel): """Request for beam reaction force calculation (simple supported beam).""" beam_length: float = Field(..., description="Beam length in meters", gt=0.0) loads: list[float] = Field(..., description="Point loads in Newtons (downward positive)") load_positions: list[float] = Field( ..., description="Positions of loads from left end in meters" ) - BeamReactionResponse Pydantic model - output schema with reaction_left, reaction_right, total_load (floats), and is_balanced (bool).
class BeamReactionResponse(BaseModel): """Response for beam reaction forces.""" reaction_left: float = Field(..., description="Reaction force at left support in Newtons") reaction_right: float = Field(..., description="Reaction force at right support in Newtons") total_load: float = Field(..., description="Total downward load in Newtons") is_balanced: bool = Field(..., description="Whether reactions balance loads") - src/chuk_mcp_physics/server.py:38-64 (registration)Registration via import of the tools.statics module in server.py - imports the module which triggers @tool decorator registration of all statics tools including calculate_beam_reactions.
# Import all tools modules to register their @tool decorated functions from .tools import ( basic, rotational, oscillations, circular_motion, collisions, conservation, fluid as fluid_tools, kinematics_tools, statics, convert_units as unit_conversion_tools, ) # Silence unused import warnings - these imports register @tool decorated functions _ = ( basic, unit_conversion_tools, rotational, oscillations, circular_motion, collisions, conservation, fluid_tools, kinematics_tools, statics, )