From 37b3ca912a770db511220d97f328dfe3e81e96ad Mon Sep 17 00:00:00 2001 From: Kai Chappell Date: Tue, 2 Dec 2025 02:55:07 +0000 Subject: [PATCH] Implement thermal calculation functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pure functions for first-order thermal response calculations: - Temperature derivative and update using Euler integration - Case temperature with self-heating via θ_ca - Junction temperature calculation via θ_jc - Steady-state junction temperature helper --- src/py_dvt_ate/simulation/physics/thermal.py | 193 +++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 src/py_dvt_ate/simulation/physics/thermal.py diff --git a/src/py_dvt_ate/simulation/physics/thermal.py b/src/py_dvt_ate/simulation/physics/thermal.py new file mode 100644 index 0000000..a11395a --- /dev/null +++ b/src/py_dvt_ate/simulation/physics/thermal.py @@ -0,0 +1,193 @@ +"""Thermal calculation functions for physics simulation. + +Pure functions implementing first-order thermal response calculations +for the coupled thermal-electrical simulation. + +All temperatures are in degrees Celsius. +All time values are in seconds. +All power values are in watts. +All thermal resistances are in degrees Celsius per watt (°C/W). +""" + + +def calculate_temperature_derivative( + current_temperature: float, + target_temperature: float, + time_constant: float, +) -> float: + """Calculate the rate of temperature change for first-order response. + + Implements: dT/dt = (T_target - T_current) / τ + + Args: + current_temperature: Current temperature in degrees Celsius. + target_temperature: Target temperature in degrees Celsius. + time_constant: Thermal time constant in seconds. + + Returns: + Rate of temperature change in degrees Celsius per second. + + Raises: + ValueError: If time_constant is not positive. + """ + if time_constant <= 0: + msg = f"Time constant must be positive, got {time_constant}" + raise ValueError(msg) + + return (target_temperature - current_temperature) / time_constant + + +def update_temperature( + current_temperature: float, + target_temperature: float, + time_constant: float, + dt: float, +) -> float: + """Calculate new temperature after a time step using Euler integration. + + Args: + current_temperature: Current temperature in degrees Celsius. + target_temperature: Target temperature in degrees Celsius. + time_constant: Thermal time constant in seconds. + dt: Time step in seconds. + + Returns: + New temperature in degrees Celsius after the time step. + + Raises: + ValueError: If time_constant or dt is not positive. + """ + if dt <= 0: + msg = f"Time step must be positive, got {dt}" + raise ValueError(msg) + + derivative = calculate_temperature_derivative( + current_temperature, target_temperature, time_constant + ) + return current_temperature + derivative * dt + + +def calculate_case_temperature_derivative( + case_temperature: float, + ambient_temperature: float, + power_dissipation: float, + time_constant: float, + theta_ca: float, +) -> float: + """Calculate rate of case temperature change including self-heating. + + Implements: dT_case/dt = (T_ambient - T_case + P_diss × θ_ca) / τ_case + + The case temperature is driven by: + - Convection/conduction to ambient (chamber) temperature + - Self-heating from power dissipation through case-to-ambient thermal resistance + + Args: + case_temperature: Current case temperature in degrees Celsius. + ambient_temperature: Ambient (chamber) temperature in degrees Celsius. + power_dissipation: Power dissipated by the device in watts. + time_constant: Case thermal time constant in seconds. + theta_ca: Thermal resistance from case to ambient in °C/W. + + Returns: + Rate of case temperature change in degrees Celsius per second. + + Raises: + ValueError: If time_constant is not positive. + """ + if time_constant <= 0: + msg = f"Time constant must be positive, got {time_constant}" + raise ValueError(msg) + + # The effective target includes self-heating contribution + thermal_drive = ambient_temperature - case_temperature + power_dissipation * theta_ca + return thermal_drive / time_constant + + +def update_case_temperature( + case_temperature: float, + ambient_temperature: float, + power_dissipation: float, + time_constant: float, + theta_ca: float, + dt: float, +) -> float: + """Calculate new case temperature after a time step. + + Args: + case_temperature: Current case temperature in degrees Celsius. + ambient_temperature: Ambient (chamber) temperature in degrees Celsius. + power_dissipation: Power dissipated by the device in watts. + time_constant: Case thermal time constant in seconds. + theta_ca: Thermal resistance from case to ambient in °C/W. + dt: Time step in seconds. + + Returns: + New case temperature in degrees Celsius after the time step. + + Raises: + ValueError: If time_constant or dt is not positive. + """ + if dt <= 0: + msg = f"Time step must be positive, got {dt}" + raise ValueError(msg) + + derivative = calculate_case_temperature_derivative( + case_temperature, + ambient_temperature, + power_dissipation, + time_constant, + theta_ca, + ) + return case_temperature + derivative * dt + + +def calculate_junction_temperature( + case_temperature: float, + power_dissipation: float, + theta_jc: float, +) -> float: + """Calculate junction temperature from case temperature and power. + + The junction temperature is assumed to respond instantaneously to + changes in case temperature and power dissipation (no thermal mass + at the die level for this simplified model). + + Implements: T_junction = T_case + P_diss × θ_jc + + Args: + case_temperature: Case temperature in degrees Celsius. + power_dissipation: Power dissipated by the device in watts. + theta_jc: Thermal resistance from junction to case in °C/W. + + Returns: + Junction temperature in degrees Celsius. + """ + return case_temperature + power_dissipation * theta_jc + + +def calculate_steady_state_junction_temperature( + ambient_temperature: float, + power_dissipation: float, + theta_jc: float, + theta_ca: float, +) -> float: + """Calculate the steady-state junction temperature. + + At steady state, the case temperature reaches equilibrium where + the heat flow through θ_ca equals the power dissipation. + + T_case_ss = T_ambient + P_diss × θ_ca + T_junction_ss = T_case_ss + P_diss × θ_jc + = T_ambient + P_diss × (θ_jc + θ_ca) + + Args: + ambient_temperature: Ambient (chamber) temperature in degrees Celsius. + power_dissipation: Power dissipated by the device in watts. + theta_jc: Thermal resistance from junction to case in °C/W. + theta_ca: Thermal resistance from case to ambient in °C/W. + + Returns: + Steady-state junction temperature in degrees Celsius. + """ + return ambient_temperature + power_dissipation * (theta_jc + theta_ca)