"""Physics engine for coupled thermal-electrical simulation. The physics engine maintains the simulation state and advances it in discrete time steps, modelling the thermal and electrical coupling between the DUT and its environment. """ from __future__ import annotations from typing import TYPE_CHECKING from py_dvt_ate.simulation.physics.models import ElectricalState, ThermalState if TYPE_CHECKING: from py_dvt_ate.simulation.physics.models.base import DUTModel class PhysicsEngine: """Coupled thermal-electrical physics simulation. Runs at a fixed timestep, updating thermal and electrical state based on the DUT model and environmental conditions. Attributes: dt: Simulation timestep in seconds. """ def __init__( self, update_rate_hz: float = 100.0, dut_model: DUTModel | None = None, ) -> None: """Initialise the physics engine. Args: update_rate_hz: Simulation update rate in Hz. Defaults to 100. dut_model: DUT model to use for electrical calculations. If None, a default model will be used when implemented. """ self.dt = 1.0 / update_rate_hz self._dut = dut_model # Thermal parameters (to be configured in Sprint 3) self._tau_chamber = 30.0 # seconds self._tau_case = 5.0 # seconds self._theta_jc = 15.0 # degC/W self._theta_ca = 5.0 # degC/W # State variables self._t_setpoint = 25.0 self._t_chamber = 25.0 self._t_case = 25.0 self._v_in = 0.0 self._i_load = 0.0 self._output_enabled = False self._sim_time = 0.0 def step(self) -> None: """Advance simulation by one timestep. Updates thermal and electrical state based on current conditions. Full implementation in Sprint 3. """ # Stub: just advance time self._sim_time += self.dt def get_thermal_state(self) -> ThermalState: """Get current thermal state snapshot. Returns: Immutable ThermalState with current temperatures. """ # Stub: return current state values return ThermalState( chamber_temperature=self._t_chamber, case_temperature=self._t_case, junction_temperature=self._t_case, # Stub: junction = case timestamp=self._sim_time, ) def get_electrical_state(self) -> ElectricalState: """Get current electrical state snapshot. Returns: Immutable ElectricalState with current electrical values. """ # Stub: return placeholder values return ElectricalState( input_voltage=self._v_in, output_voltage=0.0, # Stub: will be calculated from DUT model load_current=self._i_load if self._output_enabled else 0.0, quiescent_current=0.0, # Stub: will be calculated from DUT model power_dissipation=0.0, # Stub: will be calculated from DUT model ) def set_chamber_setpoint(self, temperature: float) -> None: """Set chamber target temperature. Args: temperature: Target temperature in degrees Celsius. """ self._t_setpoint = temperature def set_input_voltage(self, voltage: float) -> None: """Set DUT input voltage. Args: voltage: Input voltage in volts. """ self._v_in = voltage def set_load_current(self, current: float) -> None: """Set DUT load current. Args: current: Load current in amps. """ self._i_load = current def set_output_enabled(self, enabled: bool) -> None: """Enable or disable DUT power. Args: enabled: True to enable output, False to disable. """ self._output_enabled = enabled @property def simulation_time(self) -> float: """Get current simulation time in seconds.""" return self._sim_time @property def is_output_enabled(self) -> bool: """Check if DUT output is enabled.""" return self._output_enabled