SSCB Modeling and Optimization
New Blog Post
Start writing your post here...
Introduction
Write your introduction here.
Conclusion
Wrap up your thoughts here.
$code$import numpy as np
import matplotlib.pyplot as plt
# Parameter Setup
Vbus = 1200.0 # DC Bus Voltage [V]
L_line = 5.0e-6 # Line Inductance [H]
I_nom = 500.0 # Nominal pre-fault current [A]
I_trip = 1200.0 # Overcurrent trip threshold level [A]
T_amb = 60.0 # Ambient Temperature [°C]
N_series = 2
N_parallel = 1
V_BR_single_25 = 620.0
R_dyn_single = 0.0933
A_tvs, b_tvs = 7.87, 0.533
# SiC MOSFET Parameters
V_drive, V_off, Rg = 18.0, -3.0, 5.0
Rds_on, Vth, gm = 2.0e-3, 3.5, 180.0
Ciss, Cgd_min, Cgd_max = 25.0e-9, 120.0e-12, 2.0e-9
# Thermal Scaling
alpha_VBR = 0.00088
k_derate = 1.0 if T_amb <= 50.0 else 1.0 - 0.005333 * (T_amb - 50.0)
V_BR_single_T = V_BR_single_25 * (1.0 + alpha_VBR * (T_amb - 25.0))
V_BR_array_T = N_series * V_BR_single_T
R_dyn_array = (N_series / N_parallel) * R_dyn_single
N_total = N_series * N_parallel
delays = [800e-9, 1.0e-6, 4.0e-6, 10.0e-6]
delay_labels = ["800 ns", "1.0 us", "4.0 us", "10.0 us"]
def run_simulation(t_det_delay):
dt = 1.0e-9
t_end = 90.0e-6
time = np.arange(0, t_end, dt)
v_gs = np.zeros_like(time)
v_ds = np.zeros_like(time)
v_inductor = np.zeros_like(time)
i_line = np.zeros_like(time)
i_ch = np.zeros_like(time)
i_tvs_total = np.zeros_like(time)
i_line[0] = I_nom
v_gs[0] = V_drive
v_ds[0] = I_nom * Rds_on
v_inductor[0] = Vbus - v_ds[0]
state = "DETECTION_DELAY" # Measuring detection delay from fault inception t=0
t_trip_detected = 0.0
t_gate_start = None
for k in range(len(time) - 1):
t = time[k]
v_ds_curr = max(v_ds[k], 0.1)
c_gd = Cgd_min + (Cgd_max - Cgd_min) / (1.0 + (v_ds_curr / 20.0)**1.2)
v_gs_curr = v_gs[k]
if state == "DETECTION_DELAY":
v_gs[k+1] = V_drive
v_ds[k+1] = i_line[k] * Rds_on
di_line = (Vbus - v_ds[k]) / L_line
i_line[k+1] = i_line[k] + di_line * dt
if (t - t_trip_detected) >= t_det_delay:
state = "GATE_DELAY"
t_gate_start = t
elif state == "GATE_DELAY":
dv_gs = (V_off - v_gs_curr) / (Rg * Ciss)
v_gs[k+1] = v_gs_curr + dv_gs * dt
v_ds[k+1] = i_line[k] * Rds_on
di_line = (Vbus - v_ds[k]) / L_line
i_line[k+1] = i_line[k] + di_line * dt
v_gp = Vth + i_line[k+1] / gm
if v_gs[k+1] <= v_gp:
state = "MILLER"
elif state == "MILLER":
v_gp = Vth + i_line[k] / gm
v_gs[k+1] = v_gp
i_g = (v_gp - V_off) / Rg
dv_ds = i_g / c_gd
v_ds[k+1] = v_ds[k] + dv_ds * dt
di_line = (Vbus - v_ds[k]) / L_line
i_line[k+1] = i_line[k] + di_line * dt
if v_ds[k+1] >= V_BR_array_T:
state = "CLAMPED"
elif state == "CLAMPED":
dv_gs = (V_off - v_gs_curr) / (Rg * Ciss)
v_gs[k+1] = v_gs_curr + dv_gs * dt
i_ch_val = max(0.0, gm * (v_gs[k+1] - Vth))
i_tvs_est = max(0.0, i_line[k] - i_ch_val)
v_ds[k+1] = V_BR_array_T + i_tvs_est * R_dyn_array
di_line = (Vbus - v_ds[k+1]) / L_line
i_line[k+1] = max(0.0, i_line[k] + di_line * dt)
if i_line[k+1] <= 0.001:
i_line[k+1] = 0.0
v_ds[k+1] = Vbus
state = "DONE"
elif state == "DONE":
v_gs[k+1] = V_off
v_ds[k+1] = Vbus
i_line[k+1] = 0.0
i_ch[k] = max(0.0, min(i_line[k], gm * (v_gs[k] - Vth))) if v_ds[k] < V_BR_array_T else max(0.0, gm * (v_gs[k] - Vth))
i_tvs_total[k] = max(0.0, i_line[k] - i_ch[k])
v_inductor[k] = Vbus - v_ds[k]
v_inductor[-1] = 0.0
p_source = Vbus * i_line
e_source_t = np.cumsum(p_source) * dt
e_inductor_t = 0.5 * L_line * (i_line**2)
p_tvs_total = v_ds * i_tvs_total
p_tvs_single = p_tvs_total / N_total
p_mosfet = v_ds * i_ch
e_tvs_total_t = np.cumsum(p_tvs_total) * dt
e_tvs_single_t = e_tvs_total_t / N_total
e_mos_t = np.cumsum(p_mosfet) * dt
return {
'time': time, 'i_line': i_line, 'v_ds': v_ds, 'v_inductor': v_inductor,
'i_tvs_total': i_tvs_total, 'p_tvs_total': p_tvs_total, 'p_tvs_single': p_tvs_single,
'p_mosfet': p_mosfet, 'e_tvs_total_t': e_tvs_total_t, 'e_tvs_single_t': e_tvs_single_t,
'e_mos_t': e_mos_t, 'e_inductor_t': e_inductor_t, 'e_source_t': e_source_t,
't_trip_detected': t_trip_detected, 't_gate_start': t_gate_start,
't_det_delay': t_det_delay
}
results = [run_simulation(d) for d in delays]
for idx, res in enumerate(results):
print(f"Delay: {delay_labels[idx]} | Peak I: {np.max(res['i_line']):.1f} A | Peak Vds: {np.max(res['v_ds']):.1f} V | TVS Energy: {res['e_tvs_total_t'][-1]:.1f} J | Per-diode E: {res['e_tvs_single_t'][-1]:.1f} J | Peak P_tvs: {np.max(res['p_tvs_total'])/1e6:.2f} MW")
Delay: 800 ns | Peak I: 732.0 A | Peak Vds: 1414.4 V | TVS Energy: 11.2 J | Per-diode E: 5.6 J | Peak P_tvs: 1.03 MW
Delay: 1.0 us | Peak I: 778.8 A | Peak Vds: 1423.1 V | TVS Energy: 12.4 J | Per-diode E: 6.2 J | Peak P_tvs: 1.11 MW
Delay: 4.0 us | Peak I: 1483.0 A | Peak Vds: 1554.0 V | TVS Energy: 32.8 J | Per-diode E: 16.4 J | Peak P_tvs: 2.30 MW
Delay: 10.0 us | Peak I: 2902.4 A | Peak Vds: 1817.4 V | TVS Energy: 86.4 J | Per-diode E: 43.2 J | Peak P_tvs: 5.25 MW
plt.style.use('seaborn-v0_8-whitegrid' if 'seaborn-v0_8-whitegrid' in plt.style.available else 'default')
fig, axs = plt.subplots(2, 2, figsize=(14, 10))
colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728']
for idx, res in enumerate(results):
t_us = res['time'] * 1e6
d_label = delay_labels[idx]
# Subplot 1: Currents
axs[0, 0].plot(t_us, res['i_line'], color=colors[idx], label=f"$t_{{det}} = {d_label}$ ($I_{{peak}} = {np.max(res['i_line']):.0f}$ A)", linewidth=2)
# Subplot 2: Voltages Vds
axs[0, 1].plot(t_us, res['v_ds'], color=colors[idx], label=f"$t_{{det}} = {d_label}$ ($V_{{ds,max}} = {np.max(res['v_ds']):.0f}$ V)", linewidth=2)
# Subplot 3: Power
axs[1, 0].plot(t_us, res['p_tvs_total'] / 1e6, color=colors[idx], label=f"$t_{{det}} = {d_label}$ ($P_{{peak}} = {np.max(res['p_tvs_total'])/1e6:.2f}$ MW)", linewidth=2)
# Subplot 4: Energy
axs[1, 1].plot(t_us, res['e_tvs_total_t'], color=colors[idx], label=f"$t_{{det}} = {d_label}$ ($E_{{TVS}} = {res['e_tvs_total_t'][-1]:.1f}$ J)", linewidth=2)
axs[0, 0].set_title('Line Current $i_{line}(t)$ Comparison (800ns, 1$\mu$s, 4$\mu$s, 10$\mu$s)')
axs[0, 0].set_xlabel('Time ($\mu$s)')
axs[0, 0].set_ylabel('Current (A)')
axs[0, 0].set_xlim(0, 60)
axs[0, 0].legend(loc='upper right')
axs[0, 0].grid(True)
axs[0, 1].set_title('MOSFET Voltage $V_{ds}(t)$ Clamping Comparison')
axs[0, 1].set_xlabel('Time ($\mu$s)')
axs[0, 1].set_ylabel('Voltage (V)')
axs[0, 1].set_xlim(0, 60)
axs[0, 1].legend(loc='center right')
axs[0, 1].grid(True)
axs[1, 0].set_title('TVS Array Power Dissipation $P_{TVS}(t)$ Comparison')
axs[1, 0].set_xlabel('Time ($\mu$s)')
axs[1, 0].set_ylabel('Power (MW)')
axs[1, 0].set_xlim(0, 60)
axs[1, 0].legend(loc='upper right')
axs[1, 0].grid(True)
axs[1, 1].set_title('Total TVS Energy Dissipation $E_{TVS}(t)$ Comparison')
axs[1, 1].set_xlabel('Time ($\mu$s)')
axs[1, 1].set_ylabel('Energy (Joules)')
axs[1, 1].set_xlim(0, 60)
axs[1, 1].legend(loc='upper left')
axs[1, 1].grid(True)
plt.tight_layout()
plt.savefig('sscb_4delays_comparison_grid.png', dpi=300)
print("Grid comparison plot created.")
Grid comparison plot created.
def plot_individual_case(res, filename, title_suffix):
t_us = res['time'] * 1e6
t_det_delay = res['t_det_delay']
fig, axs = plt.subplots(2, 2, figsize=(14, 10))
# Subplot 1: Current & Voltage Transients
ax1 = axs[0, 0]
ax1_v = ax1.twinx()
ax1.plot(t_us, res['i_line'], 'b-', label=r'$i_{line}(t)$', linewidth=2)
ax1.plot(t_us, res['i_tvs_total'], 'r-.', label=r'$i_{TVS,total}(t)$', linewidth=2)
ax1_v.plot(t_us, res['v_ds'], 'm-', label=r'$V_{ds}(t)$ (SSCB Voltage)', linewidth=2)
ax1_v.plot(t_us, res['v_inductor'], 'darkorange', linestyle='--', label=r'$V_L(t)$ (Inductor Voltage)', linewidth=1.8)
ax1.axvline(0, color='grey', linestyle=':', label='t=0: Fault Inception')
ax1.axvspan(0, res['t_gate_start'] * 1e6, color='yellow', alpha=0.35, label=f'Detection Delay ({t_det_delay*1e6:.1f} $\mu$s)')
ax1.set_xlabel('Time ($\mu$s)')
ax1.set_ylabel('Current (A)', color='b')
ax1_v.set_ylabel('Voltage (V)', color='m')
ax1.set_title(f'SSCB Transients ($t_{{det\_delay}} = {t_det_delay*1e6:.1f}\ \mu$s, $I_{{nom}} = {I_nom:g}$A)')
ax1.set_xlim(0, 60 if t_det_delay > 5e-6 else 40)
ax1.grid(True)
lines1, labels1 = ax1.get_legend_handles_labels()
lines2, labels2 = ax1_v.get_legend_handles_labels()
ax1.legend(lines1 + lines2, labels1 + labels2, loc='center right', fontsize=8)
# Subplot 2: Power Curves
ax2 = axs[0, 1]
ax2.plot(t_us, res['p_tvs_total'] / 1e6, 'r-', label=r'$P_{TVS,array}(t)$ (MW)', linewidth=2)
ax2.plot(t_us, res['p_tvs_single'] / 1e6, 'orange', linestyle='--', label=r'$P_{TVS,single}(t)$ (MW)', linewidth=2)
ax2.plot(t_us, res['p_mosfet'] / 1e6, 'g-', label=r'$P_{MOSFET}(t)$ (MW)', linewidth=1.5)
ax2.set_xlabel('Time ($\mu$s)')
ax2.set_ylabel('Power (MW)')
ax2.set_xlim(0, 60 if t_det_delay > 5e-6 else 40)
ax2.set_title(f'Power Curves Over Time ($T_{{amb}} = {T_amb:g}^\circ$C)')
ax2.legend(loc='upper right')
ax2.grid(True)
# Subplot 3: Dynamic Energy Flow & Conservation Balance
ax3 = axs[1, 0]
ax3.plot(t_us, res['e_inductor_t'], 'b-', label=r'$E_{inductor}(t) = \frac{1}{2} L i(t)^2$ (Stored Energy)', linewidth=2)
ax3.plot(t_us, res['e_source_t'], 'k--', label=r'$E_{source}(t) = \int V_{bus} i(t) dt$ (DC Supply Input)', linewidth=1.8)
ax3.plot(t_us, res['e_tvs_total_t'], 'r-', label=r'$E_{TVS,array}(t)$ (TVS Dissipated Energy)', linewidth=2)
ax3.plot(t_us, res['e_mos_t'], 'g-', label=r'$E_{MOSFET}(t)$ (MOSFET Switching Energy)', linewidth=1.5)
ax3.set_xlim(0, 60 if t_det_delay > 5e-6 else 40)
ax3.set_xlabel('Time ($\mu$s)')
ax3.set_ylabel('Energy (Joules)')
ax3.set_title('Dynamic Energy Flow & Balance Over Time')
ax3.legend(loc='upper left', fontsize=8)
ax3.grid(True)
# Subplot 4: TVS Rating vs Operating Point
ax4 = axs[1, 1]
td_range = np.logspace(-6, -3, 100)
P_ppm_single_25_MW = (A_tvs * (td_range**-b_tvs)) / 1e3
P_ppm_array_T_MW = N_total * P_ppm_single_25_MW * k_derate
ax4.loglog(td_range * 1e6, P_ppm_array_T_MW, 'r-', label=f'{N_series}S{N_parallel}P Array Limit (60°C)', linewidth=2)
ax4.loglog(td_range * 1e6, P_ppm_single_25_MW * k_derate, 'orange', linestyle='--', label='Single Diode Limit (60°C)', linewidth=1.5)
i_tvs_tot = res['i_tvs_total']
t_demag_us = (res['time'][i_tvs_tot > 10][-1] - res['time'][i_tvs_tot > 10][0]) * 1e6 if np.any(i_tvs_tot > 10) else 1.0
P_tvs_peak_MW = np.max(res['p_tvs_total']) / 1e6
P_single_peak_MW = np.max(res['p_tvs_single']) / 1e6
ax4.plot(t_demag_us, P_tvs_peak_MW, 'ko', markersize=8, label=f'Array Operating Point ({P_tvs_peak_MW:.2f} MW)')
ax4.plot(t_demag_us, P_single_peak_MW, 'm^', markersize=8, label=f'Single Diode Stress ({P_single_peak_MW:.2f} MW)')
ax4.set_xlabel('Pulse Duration $t_d$ ($\mu$s)')
ax4.set_ylabel('Peak Pulse Power Rating (MW)')
ax4.set_title(f'TVS Capability vs Stress ($t_{{det\_delay}} = {t_det_delay*1e6:.1f}\ \mu$s)')
ax4.legend(loc='upper right')
ax4.grid(True, which='both')
plt.tight_layout()
plt.savefig(filename, dpi=300)
plot_individual_case(results[2], 'sscb_4us_detailed.png', '4us')
plot_individual_case(results[3], 'sscb_10us_detailed.png', '10us')
print("Detailed 4us and 10us plots saved.")
Detailed 4us and 10us plots saved.
Here is the mathematical model, simulation parameters, comparative results for 800 ns, 1.0 μs, 4.0 μs, and 10.0 μs detection delays, and the complete Python code for your SSCB design.
Mathematical Model & Analytical Equations
1. Fault Current Ramp Phase (0≤t<tdet_delay)
At t=0 (fault inception), the line current starts at Inom=500 A and increases linearly across line inductance L:
dtdiline(t)=LVbus−InomRds(on)≈LVbus
iline(t)=Inom+LVbus⋅t
For Vbus=1200 V and L=5.0 μH, the current ramp slope is:
dtdi=5.0 μH1200 V=240 A/\mus
The current reached at the end of the hardware detection delay (tdet_delay) is:
Idetect=Inom+(240 A/\mus)⋅tdet_delay
2. Gate Turn-Off Delay & Miller Plateau (tdet_delay≤t<t2)
Once the gate driver initiates shutoff, the gate voltage discharges from Vdrive to Miller plateau voltage Vgp:
td(off)=RgCissln(Vgp−VoffVdrive−Voff)
During the Miller plateau, the gate current discharges Cgd(Vds), causing Vds to ramp up:
dtdVds(t)=Rg⋅Cgd(Vds)Vgp−Voff
Peak fault current (Ipeak) occurs at instant tpeak when Vds(tpeak)=Vbus:
Ipeak≈Idetect+LVbus⋅td(off)+2⋅L⋅(dtdVds)Vbus2
3. TVS Clamping & Inductor Demagnetization (t≥t2)
When Vds(t)≥VBR,array(Tamb), the TVS array conducts and clamps the voltage.
Ambient Temperature Adjustment (Tamb=60∘C)
Per Figures 1 and 3 of the Littelfuse AK3 datasheet:
- Breakdown Voltage Shift (αVBR=+0.088%/∘C):
VBR,single(Tamb)=VBR,single(25∘C)⋅[1+0.00088⋅(Tamb−25∘C)]
VBR,single(60∘C)=620 V⋅[1+0.00088⋅35]=639.1 V
- Peak Pulse Power Derating Factor (kderate):
kderate(Tamb)={1.01.0−0.005333⋅(Tamb−50∘C)for Tamb≤50∘Cfor 50∘C<Tamb≤125∘C
kderate(60∘C)=1.0−0.005333×(60−50)=0.9467(94.67%)
Array Topology Scaling (Nseries×Nparallel)
For Nseries=2 and Nparallel=1:
VBR,array(60∘C)=Nseries⋅VBR,single(60∘C)=2×639.1 V=1278.2 V
Rdyn,array=(NparallelNseries)⋅Rdyn,single=(12)⋅0.0933 Ω=0.1866 Ω
Vcl,array(t)=VBR,array(60∘C)+iTVS(t)⋅Rdyn,array
Inductor Demagnetization Voltage (VL(t))
By KVL:
VL(t)=Vbus−Vcl,array(t)=1200 V−[1278.2 V+iTVS(t)⋅0.1866 Ω]
Because Vcl,array(t)>Vbus, VL(t) is negative, demagnetizing the inductor:
dtdiline(t)=LVL(t)=−LVcl,array(t)−Vbus
4. Dynamic Energy Balance & Conservation
The instantaneous stored magnetic energy in the line inductor is:
Einductor(t)=21L⋅[iline(t)]2
The cumulative energy delivered by the 1200 V DC source during fault clearance is:
Esource(t)=∫0tVbus⋅iline(τ)dτ
The total energy absorbed by the TVS array satisfies energy conservation:
ETVS,total=∫tclamptclearVcl,array(τ)⋅iTVS(τ)dτ=EL,peak+Esource,demag
ETVS,total≈EL,peak⋅(Vcl,avg−VbusVcl,avg)
Simulation Results Summary
| Metric | tdet_delay=800 ns | tdet_delay=1.0 μs | tdet_delay=4.0 μs | tdet_delay=10.0 μs |
|---|---|---|---|---|
| Detection Current (Idetect) | 692.0 A | 740.0 A | 1460.0 A | 2900.0 A |
| Peak Line Current (Ipeak) | 732.0 A | 778.8 A | 1483.0 A | 2902.4 A |
| Peak TVS Clamp Voltage (Vds,max) | 1414.4 V | 1423.1 V | 1554.0 V | 1817.4 V |
| Peak Inductor Voltage (VL,min) | −214.4 V | −223.1 V | −354.0 V | −617.4 V |
| Peak Stored Inductor Energy (EL,peak) | 1.34 J | 1.52 J | 5.50 J | 21.06 J |
| Total TVS Array Energy (ETVS,total) | 11.2 J | 12.4 J | 32.8 J | 86.4 J |
| Per-Diode TVS Energy (ETVS,single) | 5.6 J | 6.2 J | 16.4 J | 43.2 J |
| Peak TVS Array Power (Ppeak,array) | 1.03 MW | 1.11 MW | 2.30 MW | 5.25 MW |
| Per-Diode Peak Power Stress (Psingle) | 0.52 MW | 0.56 MW | 1.15 MW | 2.63 MW |
| Demagnetization Duration (tdemag) | 27.8 μs | 28.2 μs | 40.2 μs | 71.4 μs |
Graphical Outputs
1. Multi-Delay Comparison Grid (800 ns, 1.0 µs, 4.0 µs, 10.0 µs)
[http://googleusercontent.com/generated_image/721]
2. Detailed 4.0 µs Detection Delay Waveforms
[http://googleusercontent.com/generated_image/705]
3. Detailed 10.0 µs Detection Delay Waveforms
[http://googleusercontent.com/generated_image/632]
Complete Parametric Python Script
import numpy as np
import matplotlib.pyplot as plt
# ==========================================
# 1. PARAMETRIC SYSTEM CONFIGURATION
# ==========================================
Vbus = 1200.0 # DC Bus Voltage [V]
L_line = 5.0e-6 # Line Inductance [H]
I_nom = 500.0 # Nominal pre-fault current [A]
I_trip = 1200.0 # Secondary overcurrent trip threshold [A]
T_amb = 60.0 # Ambient Temperature [°C]
# TVS Array Topology (2 Series x 1 Parallel)
N_series = 2 # Series TVS diodes
N_parallel = 1 # Parallel branches
# TVS Specs (Littelfuse AK3-560C-A @ 25°C)
V_BR_single_25 = 620.0 # Breakdown voltage per diode [V]
R_dyn_single = 0.0933 # Dynamic slope resistance per diode [Ohm]
A_tvs, b_tvs = 7.87, 0.533 # Datasheet Fig 5 curve fit parameters
# Infineon 62mm SiC MOSFET Module Specs
V_drive, V_off, Rg = 18.0, -3.0, 5.0
Rds_on, Vth, gm = 2.0e-3, 3.5, 180.0
Ciss, Cgd_min, Cgd_max = 25.0e-9, 120.0e-12, 2.0e-9
# Thermal & Array Derating
alpha_VBR = 0.00088 # Temperature coefficient (+0.088 %/°C)
k_derate = 1.0 if T_amb <= 50.0 else 1.0 - 0.005333 * (T_amb - 50.0)
V_BR_single_T = V_BR_single_25 * (1.0 + alpha_VBR * (T_amb - 25.0))
V_BR_array_T = N_series * V_BR_single_T
R_dyn_array = (N_series / N_parallel) * R_dyn_single
N_total = N_series * N_parallel
# Detection delays to evaluate
delays = [800e-9, 1.0e-6, 4.0e-6, 10.0e-6]
delay_labels = ["800 ns", "1.0 us", "4.0 us", "10.0 us"]
# ==========================================
# 2. TRANSIENT SIMULATION ENGINE
# ==========================================
def run_simulation(t_det_delay):
dt = 1.0e-9 # Integration time step [s]
t_end = 90.0e-6 # Simulation window [s]
time = np.arange(0, t_end, dt)
v_gs = np.zeros_like(time)
v_ds = np.zeros_like(time)
v_inductor = np.zeros_like(time)
i_line = np.zeros_like(time)
i_ch = np.zeros_like(time)
i_tvs_total = np.zeros_like(time)
# Initial condition at fault inception (t = 0)
i_line[0] = I_nom
v_gs[0] = V_drive
v_ds[0] = I_nom * Rds_on
v_inductor[0] = Vbus - v_ds[0]
state = "DETECTION_DELAY" # Slope detection triggers at t=0
t_trip_detected = 0.0
t_gate_start = None
for k in range(len(time) - 1):
t = time[k]
v_ds_curr = max(v_ds[k], 0.1)
c_gd = Cgd_min + (Cgd_max - Cgd_min) / (1.0 + (v_ds_curr / 20.0)**1.2)
v_gs_curr = v_gs[k]
if state == "DETECTION_DELAY":
v_gs[k+1] = V_drive
v_ds[k+1] = i_line[k] * Rds_on
di_line = (Vbus - v_ds[k]) / L_line
i_line[k+1] = i_line[k] + di_line * dt
if (t - t_trip_detected) >= t_det_delay:
state = "GATE_DELAY"
t_gate_start = t
elif state == "GATE_DELAY":
dv_gs = (V_off - v_gs_curr) / (Rg * Ciss)
v_gs[k+1] = v_gs_curr + dv_gs * dt
v_ds[k+1] = i_line[k] * Rds_on
di_line = (Vbus - v_ds[k]) / L_line
i_line[k+1] = i_line[k] + di_line * dt
v_gp = Vth + i_line[k+1] / gm
if v_gs[k+1] <= v_gp:
state = "MILLER"
elif state == "MILLER":
v_gp = Vth + i_line[k] / gm
v_gs[k+1] = v_gp
i_g = (v_gp - V_off) / Rg
dv_ds = i_g / c_gd
v_ds[k+1] = v_ds[k] + dv_ds * dt
di_line = (Vbus - v_ds[k]) / L_line
i_line[k+1] = i_line[k] + di_line * dt
if v_ds[k+1] >= V_BR_array_T:
state = "CLAMPED"
elif state == "CLAMPED":
dv_gs = (V_off - v_gs_curr) / (Rg * Ciss)
v_gs[k+1] = v_gs_curr + dv_gs * dt
i_ch_val = max(0.0, gm * (v_gs[k+1] - Vth))
i_tvs_est = max(0.0, i_line[k] - i_ch_val)
v_ds[k+1] = V_BR_array_T + i_tvs_est * R_dyn_array
di_line = (Vbus - v_ds[k+1]) / L_line
i_line[k+1] = max(0.0, i_line[k] + di_line * dt)
if i_line[k+1] <= 0.001:
i_line[k+1] = 0.0
v_ds[k+1] = Vbus
state = "DONE"
elif state == "DONE":
v_gs[k+1] = V_off
v_ds[k+1] = Vbus
i_line[k+1] = 0.0
i_ch[k] = max(0.0, min(i_line[k], gm * (v_gs[k] - Vth))) if v_ds[k] < V_BR_array_T else max(0.0, gm * (v_gs[k] - Vth))
i_tvs_total[k] = max(0.0, i_line[k] - i_ch[k])
v_inductor[k] = Vbus - v_ds[k]
v_inductor[-1] = 0.0
p_source = Vbus * i_line
e_source_t = np.cumsum(p_source) * dt
e_inductor_t = 0.5 * L_line * (i_line**2)
p_tvs_total = v_ds * i_tvs_total
p_tvs_single = p_tvs_total / N_total
p_mosfet = v_ds * i_ch
e_tvs_total_t = np.cumsum(p_tvs_total) * dt
e_tvs_single_t = e_tvs_total_t / N_total
e_mos_t = np.cumsum(p_mosfet) * dt
return {
'time': time, 'i_line': i_line, 'v_ds': v_ds, 'v_inductor': v_inductor,
'i_tvs_total': i_tvs_total, 'p_tvs_total': p_tvs_total, 'p_tvs_single': p_tvs_single,
'p_mosfet': p_mosfet, 'e_tvs_total_t': e_tvs_total_t, 'e_tvs_single_t': e_tvs_single_t,
'e_mos_t': e_mos_t, 'e_inductor_t': e_inductor_t, 'e_source_t': e_source_t,
't_trip_detected': t_trip_detected, 't_gate_start': t_gate_start,
't_det_delay': t_det_delay
}
results = [run_simulation(d) for d in delays]
# ==========================================
# 3. MULTI-DELAY COMPARISON GRID (4 PANELS)
# ==========================================
plt.style.use('seaborn-v0_8-whitegrid' if 'seaborn-v0_8-whitegrid' in plt.style.available else 'default')
fig, axs = plt.subplots(2, 2, figsize=(14, 10))
colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728']
for idx, res in enumerate(results):
t_us = res['time'] * 1e6
d_label = delay_labels[idx]
axs[0, 0].plot(t_us, res['i_line'], color=colors[idx], label=f"$t_{{det}} = {d_label}$ ($I_{{peak}} = {np.max(res['i_line']):.0f}$ A)", linewidth=2)
axs[0, 1].plot(t_us, res['v_ds'], color=colors[idx], label=f"$t_{{det}} = {d_label}$ ($V_{{ds,max}} = {np.max(res['v_ds']):.0f}$ V)", linewidth=2)
axs[1, 0].plot(t_us, res['p_tvs_total'] / 1e6, color=colors[idx], label=f"$t_{{det}} = {d_label}$ ($P_{{peak}} = {np.max(res['p_tvs_total'])/1e6:.2f}$ MW)", linewidth=2)
axs[1, 1].plot(t_us, res['e_tvs_total_t'], color=colors[idx], label=f"$t_{{det}} = {d_label}$ ($E_{{TVS}} = {res['e_tvs_total_t'][-1]:.1f}$ J)", linewidth=2)
axs[0, 0].set_title('Line Current $i_{line}(t)$ Comparison')
axs[0, 0].set_xlabel('Time ($\mu$s)')
axs[0, 0].set_ylabel('Current (A)')
axs[0, 0].set_xlim(0, 60)
axs[0, 0].legend(loc='upper right')
axs[0, 0].grid(True)
axs[0, 1].set_title('MOSFET Voltage $V_{ds}(t)$ Clamping Comparison')
axs[0, 1].set_xlabel('Time ($\mu$s)')
axs[0, 1].set_ylabel('Voltage (V)')
axs[0, 1].set_xlim(0, 60)
axs[0, 1].legend(loc='center right')
axs[0, 1].grid(True)
axs[1, 0].set_title('TVS Array Power Dissipation $P_{TVS}(t)$ Comparison')
axs[1, 0].set_xlabel('Time ($\mu$s)')
axs[1, 0].set_ylabel('Power (MW)')
axs[1, 0].set_xlim(0, 60)
axs[1, 0].legend(loc='upper right')
axs[1, 0].grid(True)
axs[1, 1].set_title('Total TVS Energy Dissipation $E_{TVS}(t)$ Comparison')
axs[1, 1].set_xlabel('Time ($\mu$s)')
axs[1, 1].set_ylabel('Energy (Joules)')
axs[1, 1].set_xlim(0, 60)
axs[1, 1].legend(loc='upper left')
axs[1, 1].grid(True)
plt.tight_layout()
plt.show()
Comments
No comments yet. Be the first to comment!