Skip to main content
Glama
IBM

Physics MCP Server

by IBM

calculate_inelastic_collision_3d

Calculate realistic 3D collisions with adjustable coefficient of restitution to model energy loss. Determines final velocities, momentum, kinetic energy changes, and energy lost.

Instructions

Calculate 3D collision with coefficient of restitution.

Models realistic collisions where some kinetic energy is lost.
Coefficient of restitution (e) determines how much energy is retained.

Args:
    mass1: Mass of object 1 in kg
    velocity1: Velocity of object 1 [x, y, z] in m/s (or JSON string)
    mass2: Mass of object 2 in kg
    velocity2: Velocity of object 2 [x, y, z] in m/s (or JSON string)
    coefficient_of_restitution: e (0.0 = perfectly inelastic, 1.0 = perfectly elastic)

Returns:
    Dict containing:
        - final_velocity1: Final velocity [x, y, z] in m/s
        - final_velocity2: Final velocity [x, y, z] in m/s
        - initial_momentum: Total initial momentum [x, y, z]
        - final_momentum: Total final momentum [x, y, z]
        - initial_kinetic_energy: Total initial KE in Joules
        - final_kinetic_energy: Total final KE in Joules
        - energy_loss: Energy lost in Joules
        - energy_loss_percent: % of energy lost

Coefficient of restitution values:
    - e = 0.0: Perfectly inelastic (clay, putty) - objects stick
    - e = 0.5: Very inelastic (wet clay)
    - e = 0.7: Moderately elastic (basketball)
    - e = 0.9: Highly elastic (Super Ball)
    - e = 1.0: Perfectly elastic (ideal, no energy loss)

Tips for LLMs:
    - Momentum is always conserved (regardless of e)
    - Energy lost = (1 - e²) × initial KE in center-of-mass frame
    - Use e=1.0 for billiard balls, e=0.0 for car crashes

Example - Car crash:
    result = await calculate_inelastic_collision_3d(
        mass1=1500,  # kg
        velocity1=[20, 0, 0],  # 20 m/s east
        mass2=1200,  # kg
        velocity2=[-15, 0, 0],  # 15 m/s west
        coefficient_of_restitution=0.1  # very inelastic
    )
    # Massive energy loss, objects nearly stick together

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
mass1Yes
velocity1Yes
mass2Yes
velocity2Yes
coefficient_of_restitutionNo

Implementation Reference

  • Core implementation: calculates 3D inelastic collision with coefficient of restitution using conservation of momentum and the coefficient of restitution formula to compute final velocities, momentum, and energy analysis.
    def calculate_inelastic_collision_3d(
        request: InelasticCollision3DRequest,
    ) -> InelasticCollision3DResponse:
        """Calculate 3D collision with coefficient of restitution.
    
        Uses conservation of momentum and coefficient of restitution to solve
        for final velocities in 3D.
    
        For coefficient of restitution e:
        - e = 0: Perfectly inelastic (objects stick together)
        - 0 < e < 1: Inelastic (some energy lost)
        - e = 1: Perfectly elastic (no energy lost)
    
        Args:
            request: Inelastic collision request
    
        Returns:
            Final velocities, momentum, and energy analysis
        """
        m1 = request.mass1
        v1 = request.velocity1
        m2 = request.mass2
        v2 = request.velocity2
        e = request.coefficient_of_restitution
    
        # Calculate initial momentum
        p1_initial = _vector_scale(v1, m1)
        p2_initial = _vector_scale(v2, m2)
        p_total = _vector_add(p1_initial, p2_initial)
    
        # Calculate initial kinetic energy
        ke1_initial = 0.5 * m1 * _dot_product(v1, v1)
        ke2_initial = 0.5 * m2 * _dot_product(v2, v2)
        ke_total_initial = ke1_initial + ke2_initial
    
        # For 3D collision, we need to work in the collision frame
        # Relative velocity
        v_rel = _vector_subtract(v1, v2)
        v_rel_mag = _vector_magnitude(v_rel)
    
        if v_rel_mag < 1e-10:
            # Objects already at same velocity
            return InelasticCollision3DResponse(
                final_velocity1=v1,
                final_velocity2=v2,
                initial_momentum=p_total,
                final_momentum=p_total,
                initial_kinetic_energy=ke_total_initial,
                final_kinetic_energy=ke_total_initial,
                energy_loss=0.0,
                energy_loss_percent=0.0,
            )
    
        # Unit vector in direction of collision (along relative velocity)
        n = _vector_scale(v_rel, 1.0 / v_rel_mag)
    
        # Velocity components along collision normal
        v1n = _dot_product(v1, n)
        v2n = _dot_product(v2, n)
    
        # Calculate final velocities along normal using 1D collision formulas with restitution
        # Conservation of momentum: m1*v1n + m2*v2n = m1*v1n' + m2*v2n'
        # Coefficient of restitution: e = (v2n' - v1n') / (v1n - v2n)
    
        # Solving these two equations:
        v1n_final = ((m1 - e * m2) * v1n + m2 * (1 + e) * v2n) / (m1 + m2)
        v2n_final = ((m2 - e * m1) * v2n + m1 * (1 + e) * v1n) / (m1 + m2)
    
        # Calculate change in normal velocity
        delta_v1n = v1n_final - v1n
        delta_v2n = v2n_final - v2n
    
        # Apply changes to original velocities
        v1_final = _vector_add(v1, _vector_scale(n, delta_v1n))
        v2_final = _vector_add(v2, _vector_scale(n, delta_v2n))
    
        # Calculate final momentum and energy
        p1_final = _vector_scale(v1_final, m1)
        p2_final = _vector_scale(v2_final, m2)
        p_final = _vector_add(p1_final, p2_final)
    
        ke1_final = 0.5 * m1 * _dot_product(v1_final, v1_final)
        ke2_final = 0.5 * m2 * _dot_product(v2_final, v2_final)
        ke_total_final = ke1_final + ke2_final
    
        energy_loss = ke_total_initial - ke_total_final
        energy_loss_percent = (energy_loss / ke_total_initial * 100.0) if ke_total_initial > 0 else 0.0
    
        return InelasticCollision3DResponse(
            final_velocity1=v1_final,
            final_velocity2=v2_final,
            initial_momentum=p_total,
            final_momentum=p_final,
            initial_kinetic_energy=ke_total_initial,
            final_kinetic_energy=ke_total_final,
            energy_loss=energy_loss,
            energy_loss_percent=energy_loss_percent,
        )
  • MCP tool handler: async function decorated with @tool that parses inputs (velocity as list or JSON string), creates an InelasticCollision3DRequest, delegates to the core calculate_inelastic_collision_3d, and returns the response as a dict.
    @tool  # type: ignore[arg-type]
    async def calculate_inelastic_collision_3d(
        mass1: float,
        velocity1: Union[list[float], str],
        mass2: float,
        velocity2: Union[list[float], str],
        coefficient_of_restitution: float = 0.0,
    ) -> dict:
        """Calculate 3D collision with coefficient of restitution.
    
        Models realistic collisions where some kinetic energy is lost.
        Coefficient of restitution (e) determines how much energy is retained.
    
        Args:
            mass1: Mass of object 1 in kg
            velocity1: Velocity of object 1 [x, y, z] in m/s (or JSON string)
            mass2: Mass of object 2 in kg
            velocity2: Velocity of object 2 [x, y, z] in m/s (or JSON string)
            coefficient_of_restitution: e (0.0 = perfectly inelastic, 1.0 = perfectly elastic)
    
        Returns:
            Dict containing:
                - final_velocity1: Final velocity [x, y, z] in m/s
                - final_velocity2: Final velocity [x, y, z] in m/s
                - initial_momentum: Total initial momentum [x, y, z]
                - final_momentum: Total final momentum [x, y, z]
                - initial_kinetic_energy: Total initial KE in Joules
                - final_kinetic_energy: Total final KE in Joules
                - energy_loss: Energy lost in Joules
                - energy_loss_percent: % of energy lost
    
        Coefficient of restitution values:
            - e = 0.0: Perfectly inelastic (clay, putty) - objects stick
            - e = 0.5: Very inelastic (wet clay)
            - e = 0.7: Moderately elastic (basketball)
            - e = 0.9: Highly elastic (Super Ball)
            - e = 1.0: Perfectly elastic (ideal, no energy loss)
    
        Tips for LLMs:
            - Momentum is always conserved (regardless of e)
            - Energy lost = (1 - e²) × initial KE in center-of-mass frame
            - Use e=1.0 for billiard balls, e=0.0 for car crashes
    
        Example - Car crash:
            result = await calculate_inelastic_collision_3d(
                mass1=1500,  # kg
                velocity1=[20, 0, 0],  # 20 m/s east
                mass2=1200,  # kg
                velocity2=[-15, 0, 0],  # 15 m/s west
                coefficient_of_restitution=0.1  # very inelastic
            )
            # Massive energy loss, objects nearly stick together
        """
        # Parse inputs
        parsed_v1 = json.loads(velocity1) if isinstance(velocity1, str) else velocity1
        parsed_v2 = json.loads(velocity2) if isinstance(velocity2, str) else velocity2
    
        from ..collisions import (
            InelasticCollision3DRequest,
            calculate_inelastic_collision_3d as calc_coll,
        )
    
        request = InelasticCollision3DRequest(
            mass1=mass1,
            velocity1=parsed_v1,
            mass2=mass2,
            velocity2=parsed_v2,
            coefficient_of_restitution=coefficient_of_restitution,
        )
        response = calc_coll(request)
        return response.model_dump()
  • InelasticCollision3DRequest schema: Pydantic model with mass1, velocity1, mass2, velocity2, and coefficient_of_restitution (0.0-1.0) fields.
    class InelasticCollision3DRequest(BaseModel):
        """Request for 3D inelastic collision calculation."""
    
        mass1: float = Field(..., description="Mass of object 1 in kg", gt=0.0)
        velocity1: list[float] = Field(..., description="Velocity of object 1 [x, y, z] in m/s")
        mass2: float = Field(..., description="Mass of object 2 in kg", gt=0.0)
        velocity2: list[float] = Field(..., description="Velocity of object 2 [x, y, z] in m/s")
        coefficient_of_restitution: float = Field(
            default=0.0,
            description="Coefficient of restitution (0.0=perfectly inelastic, 1.0=perfectly elastic)",
            ge=0.0,
            le=1.0,
        )
  • InelasticCollision3DResponse schema: Pydantic model with final velocities, momentum, kinetic energy, energy loss, and energy loss percent fields.
    class InelasticCollision3DResponse(BaseModel):
        """Response for 3D inelastic collision calculation."""
    
        final_velocity1: list[float] = Field(
            ..., description="Final velocity of object 1 [x, y, z] in m/s"
        )
        final_velocity2: list[float] = Field(
            ..., description="Final velocity of object 2 [x, y, z] in m/s"
        )
        initial_momentum: list[float] = Field(
            ..., description="Total initial momentum [x, y, z] in kg⋅m/s"
        )
        final_momentum: list[float] = Field(..., description="Total final momentum [x, y, z] in kg⋅m/s")
        initial_kinetic_energy: float = Field(..., description="Total initial kinetic energy in Joules")
        final_kinetic_energy: float = Field(..., description="Total final kinetic energy in Joules")
        energy_loss: float = Field(..., description="Kinetic energy lost in collision in Joules")
        energy_loss_percent: float = Field(..., description="Percentage of kinetic energy lost")
  • The @tool decorator registers calculate_inelastic_collision_3d as an MCP tool in the server.
    @tool  # type: ignore[arg-type]
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It discloses that momentum is always conserved and explains energy loss behavior with the coefficient. It does not mention any side effects, limitations, or edge cases, but the core behavioral traits are well-covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is thorough but somewhat lengthy. It is well-structured with sections (Args, Returns, Tips, Example), which aids clarity. However, some parts (like Tips for LLMs) add valuable context but could be more concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the absence of output schema and sparse input schema, the description fully compensates by detailing all parameters, return values, and physical context. It is complete for an agent to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description adds extensive meaning: units (kg, m/s), format of velocity (array or JSON string), range and defaults for coefficient, and full return fields. This is far beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it calculates 3D inelastic collisions with a coefficient of restitution, differentiating it from sibling tools like calculate_elastic_collision_3d. The verb 'calculate' and resource '3D collision' are specific, and the context of energy loss is explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use the tool, including coefficient of restitution values and example use cases (e.g., billiard balls vs. car crashes). It also clarifies momentum conservation and offers tips for LLMs, leaving little ambiguity about appropriate scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/IBM/chuk-mcp-physics'

If you have feedback or need assistance with the MCP directory API, please join our Discord server