"""Energy and particle simulation utilities. This module provides simple functions to model energy production/consumption and basic particle interactions. The functions here are not intended to approximate real physical systems with high accuracy; rather, they serve as illustrative examples of how one might compute energy flows or elastic collisions in software. """ from __future__ import annotations from typing import Tuple def solar_panel_output(power_watt: float, hours: float, efficiency: float = 0.15) -> float: """Compute the energy generated by a solar panel. Parameters ---------- power_watt : float The nominal power rating of the panel in watts (W). Must be non‑negative. hours : float Number of hours the panel operates under rated conditions. Must be non‑negative. efficiency : float, optional Conversion efficiency (0 ≤ efficiency ≤ 1). Defaults to 0.15 (15 %). Returns ------- float Energy produced in joules (J). Notes ----- The energy is computed as `power_watt * efficiency * hours * 3600`. In practice, solar panel output varies with irradiance, temperature and other factors. This simplified function treats the rated power and efficiency as constants over the specified duration. """ if power_watt < 0 or hours < 0: raise ValueError("Power and hours must be non-negative") if efficiency < 0 or efficiency > 1: raise ValueError("Efficiency must be between 0 and 1") # Convert hours to seconds to compute energy in joules return power_watt * efficiency * hours * 3600.0 def battery_discharge(capacity_mAh: float, load_mA: float, hours: float) -> float: """Estimate remaining battery capacity after discharging at a constant load. Parameters ---------- capacity_mAh : float Initial battery capacity in milliampere-hours (mAh). load_mA : float Current draw in milliamperes (mA). hours : float Duration of the load in hours. Returns ------- float Remaining capacity in milliampere-hours (mAh). Will be zero or positive; if the calculated value is negative, zero is returned. """ if capacity_mAh < 0 or load_mA < 0 or hours < 0: raise ValueError("Capacity, load and time must be non-negative") consumed = load_mA * hours remaining = capacity_mAh - consumed return remaining if remaining > 0 else 0.0 def simulate_particle_collision( m1: float, v1: float, m2: float, v2: float ) -> Tuple[float, float]: """Simulate a one-dimensional elastic collision between two particles. Parameters ---------- m1, m2 : float Masses of the two particles in kilograms (kg). Must be positive. v1, v2 : float Initial velocities of the two particles along one axis (m/s). Positive velocities indicate motion in the same direction; negative values represent motion in the opposite direction. Returns ------- (float, float) A tuple `(v1_final, v2_final)` giving the final velocities of the particles after an elastic collision, assuming conservation of momentum and kinetic energy. If either mass is zero, the function raises ``ValueError``. """ if m1 <= 0 or m2 <= 0: raise ValueError("Masses must be positive") # 1D elastic collision formulas v1_final = ((m1 - m2) / (m1 + m2)) * v1 + ((2 * m2) / (m1 + m2)) * v2 v2_final = ((2 * m1) / (m1 + m2)) * v1 + ((m2 - m1) / (m1 + m2)) * v2 return v1_final, v2_final