#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct VaractorParams {
pub cj0: f64,
pub phi: f64,
pub m: f64,
}
impl Default for VaractorParams {
fn default() -> Self {
Self {
cj0: 10e-12,
phi: 0.7,
m: 0.5,
}
}
}
pub fn junction_capacitance(v: f64, params: &VaractorParams) -> f64 {
let v_clamped = v.min(0.9 * params.phi);
let denom = (1.0 - v_clamped / params.phi).powf(params.m);
params.cj0 / denom.max(1e-6) }
pub fn varactor_companion(v_prev: f64, dt: f64, params: &VaractorParams) -> (f64, f64) {
if dt <= 0.0 {
return (0.0, 0.0);
}
let cj = junction_capacitance(v_prev, params);
let g_eq = cj / dt;
let i_eq = -g_eq * v_prev; (g_eq, i_eq)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn varactor_dc_is_open_circuit() {
let params = VaractorParams::default();
let (g_eq, i_eq) = varactor_companion(0.0, 0.0, ¶ms);
assert_eq!(g_eq, 0.0);
assert_eq!(i_eq, 0.0);
}
#[test]
fn varactor_dc_is_open_circuit_at_nonzero_voltage() {
let params = VaractorParams::default();
let (g_eq, i_eq) = varactor_companion(-5.0, 0.0, ¶ms);
assert_eq!(g_eq, 0.0);
assert_eq!(i_eq, 0.0);
}
#[test]
fn varactor_capacitance_decreases_at_reverse_bias() {
let params = VaractorParams::default();
let c_at_zero = junction_capacitance(0.0, ¶ms);
let c_at_reverse = junction_capacitance(-2.0, ¶ms);
assert!(
c_at_zero > c_at_reverse,
"C(0V)={} should be > C(-2V)={}",
c_at_zero,
c_at_reverse
);
}
#[test]
fn varactor_transient_g_eq_is_cj_over_dt() {
let params = VaractorParams::default();
let v_prev = 0.0;
let dt = 1e-6;
let (g_eq, i_eq) = varactor_companion(v_prev, dt, ¶ms);
let expected_g = params.cj0 / dt;
assert!(
(g_eq - expected_g).abs() < 1e-20,
"g_eq={} expected {}",
g_eq,
expected_g
);
assert_eq!(i_eq, 0.0);
}
#[test]
fn varactor_capacitance_clamped_near_phi() {
let params = VaractorParams::default();
let c_clamped = junction_capacitance(0.65, ¶ms);
assert!(c_clamped.is_finite(), "capacitance should be finite");
assert!(
c_clamped > params.cj0,
"forward-biased C={} should be > cj0={}",
c_clamped,
params.cj0
);
}
}