Source code for transientbvd.activation

"""
TransientBVD - Activation Transient Analysis

This module contains functions for analyzing the activation transient
response of resonant circuits modeled by the Butterworth-Van Dyke (BVD)
equivalent circuit.
"""

from typing import Tuple, Optional
import math

import numpy as np

from transientbvd.transducer import Transducer






[docs] def activation_potential( transducer: Transducer, ucw: float, ub: float ) -> Tuple[float, float, float, float, float]: """ Evaluate the potential improvement in transient response time when using overboosting in the activation scenario. Parameters ---------- transducer : Transducer The transducer containing the circuit parameters. ucw : float Continuous-wave voltage amplitude in volts. ub : float Overboost voltage amplitude in volts. Returns ------- Tuple[float, float, float, float, float] (t_sw, tau_no_boost, tau_with_boost, delta_time, percentage_improvement). """ # Validate input parameters assert ucw > 0, "ucw must be positive." if ub <= ucw: raise ValueError("ub must be greater than ucw.") t_sw = switching_time(transducer, ub, ucw) tau_no_boost = activation_4tau(transducer, ucw) tau_with_boost = activation_4tau(transducer, ucw, ub, t_sw) delta_time = tau_no_boost - tau_with_boost percentage_improvement = ( (delta_time / tau_no_boost) * 100 if tau_no_boost > 0 else 0.0 ) return t_sw, tau_no_boost, tau_with_boost, delta_time, percentage_improvement
[docs] def activation_current( t: float, transducer: Transducer, ucw: float, ub: Optional[float] = None, t_sw: Optional[float] = None, ) -> float: """ Compute the transient current response for an activation BVD model. Parameters ---------- t : float Time in seconds. If `np.inf` is provided, this returns the steady-state current (`U_cw / R_s`). transducer : Transducer The transducer containing the circuit parameters. ucw : float Operating (continuous-wave) voltage amplitude in volts. Must be > 0. ub : float, optional Overboost voltage amplitude in volts. If provided, must be > 0 and > `U_cw`. t_sw : float, optional Switching time in seconds. If provided, must be > 0. If not provided but `ub` is given, it is computed via `switching_time`. Returns ------- float The transient current at time `t`. """ assert t >= 0, "Time must be non-negative." # Extract circuit parameters rs, ls, cs = transducer.rs, transducer.ls, transducer.cs # Validate input parameters assert ucw > 0, "ucw must be positive." assert rs > 0 and ls > 0 and cs > 0, "Circuit parameters must be positive." if t == np.inf: return abs(ucw / rs) if ub is not None: assert ub > ucw, "ub must be greater than ucw." if t_sw is not None: if ub is None: raise ValueError("t_sw cannot be provided without ub.") assert t_sw > 0, "t_sw must be positive." # Compute switching time if needed if ub is not None and t_sw is None: t_sw = switching_time(transducer, ub, ucw) # Compute response w_r = 1.0 / math.sqrt(ls * cs) tau = 2.0 * ls / rs if ub is not None and t_sw is not None: if t < t_sw: return (ub / rs) * math.cos(w_r * t) * (1 - math.exp(-t / tau)) # else t >= t_sw amp_t_sw = (ub / rs) * (1 - math.exp(-t_sw / tau)) phase_offset = w_r * t_sw return amp_t_sw * math.exp(-(t - t_sw) / tau) * math.cos( w_r * (t - t_sw) + phase_offset ) + (ucw / rs) * math.cos(w_r * (t - t_sw) + phase_offset) * ( 1 - math.exp(-(t - t_sw) / tau) ) return (ucw / rs) * math.cos(w_r * t) * (1 - math.exp(-t / tau))
[docs] def switching_time(transducer: Transducer, ub: float, ucw: float) -> float: """ Calculate the switching time for the transient response in the activation scenario. Parameters ---------- transducer : Transducer The transducer containing the circuit parameters. ub : float Overboost voltage amplitude in volts. ucw : float Continuous-wave voltage amplitude in volts. Returns ------- float Switching time in seconds. """ rs, ls = transducer.rs, transducer.ls assert ucw > 0, "ucw must be positive." assert ub > 0, "ub must be positive." if ub <= ucw: raise ValueError("ub must be greater than ucw.") assert rs > 0 and ls > 0, "Circuit parameters must be positive." tau = 2.0 * ls / rs return -tau * math.log(1.0 - (ucw / ub))
[docs] def activation_4tau( transducer: Transducer, ucw: float, ub: Optional[float] = None, t_sw: Optional[float] = None, ) -> float: """ Calculate the time at which the oscillation amplitude first reaches 98.2% of the steady-state current in the activation scenario. Parameters ---------- transducer : Transducer The transducer containing the circuit parameters. ucw : float Continuous-wave voltage amplitude in volts. ub : float, optional Overboost voltage amplitude in volts. t_sw : float, optional Switching time in seconds. Returns ------- float The 4τ time in seconds. """ rs, ls, cs, _ = transducer.rs, transducer.ls, transducer.cs, transducer.c0 assert ucw > 0, "ucw must be positive." assert rs > 0 and ls > 0 and cs > 0, "Circuit parameters must be positive." if ub is not None: assert ub > 0, "ub must be positive." if ub <= ucw: raise ValueError("ub must be greater than ucw.") if ub is not None and t_sw is None: t_sw = switching_time(transducer, ub, ucw) tau = 2.0 * ls / rs steady_state_current = ucw / rs threshold = 0.982 * steady_state_current # 98.2% threshold -> 4τ if ub is not None and t_sw is not None: amp_t_sw = (ub / rs) * (1 - math.exp(-t_sw / tau)) if amp_t_sw >= threshold: return t_sw return tau * math.log( (ub * math.exp(t_sw / tau) - ub - ucw * math.exp(t_sw / tau)) / (rs * threshold - ucw) ) return -tau * math.log(1.0 - (threshold * rs / ucw))