smart-blog
Science & systems
← Back to posts

SSCB Modeling and Optimization

By Nazim

New Blog Post

Start writing your post here...

Introduction

Write your introduction here.

Conclusion

Wrap up your thoughts here.

text
$code$
python
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")

text
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

python
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.")

text
Grid comparison plot created.

python
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.")

text
Detailed 4us and 10us plots saved.

Here is the mathematical model, simulation parameters, comparative results for 800 ns800\text{ ns}, 1.0 μs1.0\ \mu\text{s}, 4.0 μs4.0\ \mu\text{s}, and 10.0 μs10.0\ \mu\text{s} detection delays, and the complete Python code for your SSCB design.


Mathematical Model & Analytical Equations

1. Fault Current Ramp Phase (0t<tdet_delay0 \le t < t_{det\_delay})

At t=0t = 0 (fault inception), the line current starts at Inom=500 AI_{nom} = 500\text{ A} and increases linearly across line inductance LL:

diline(t)dt=VbusInomRds(on)LVbusL\frac{di_{line}(t)}{dt} = \frac{V_{bus} - I_{nom} R_{ds(on)}}{L} \approx \frac{V_{bus}}{L}

iline(t)=Inom+VbusLti_{line}(t) = I_{nom} + \frac{V_{bus}}{L} \cdot t

For Vbus=1200 VV_{bus} = 1200\text{ V} and L=5.0 μHL = 5.0\ \mu\text{H}, the current ramp slope is:

didt=1200 V5.0 μH=240 A/\mus\frac{di}{dt} = \frac{1200\text{ V}}{5.0\ \mu\text{H}} = 240\text{ A/\mu s}

The current reached at the end of the hardware detection delay (tdet_delayt_{det\_delay}) is:

Idetect=Inom+(240 A/\mus)tdet_delayI_{detect} = I_{nom} + \left(240\text{ A/\mu s}\right) \cdot t_{det\_delay}

2. Gate Turn-Off Delay & Miller Plateau (tdet_delayt<t2t_{det\_delay} \le t < t_2)

Once the gate driver initiates shutoff, the gate voltage discharges from VdriveV_{drive} to Miller plateau voltage VgpV_{gp}:

td(off)=RgCissln(VdriveVoffVgpVoff)t_{d(off)} = R_g C_{iss} \ln \left( \frac{V_{drive} - V_{off}}{V_{gp} - V_{off}} \right)

During the Miller plateau, the gate current discharges Cgd(Vds)C_{gd}(V_{ds}), causing VdsV_{ds} to ramp up:

dVds(t)dt=VgpVoffRgCgd(Vds)\frac{dV_{ds}(t)}{dt} = \frac{V_{gp} - V_{off}}{R_g \cdot C_{gd}(V_{ds})}

Peak fault current (IpeakI_{peak}) occurs at instant tpeakt_{peak} when Vds(tpeak)=VbusV_{ds}(t_{peak}) = V_{bus}:

IpeakIdetect+VbusLtd(off)+Vbus22L(dVdsdt)I_{peak} \approx I_{detect} + \frac{V_{bus}}{L} \cdot t_{d(off)} + \frac{V_{bus}^2}{2 \cdot L \cdot \left(\frac{dV_{ds}}{dt}\right)}

3. TVS Clamping & Inductor Demagnetization (tt2t \ge t_2)

When Vds(t)VBR,array(Tamb)V_{ds}(t) \ge V_{BR,array}(T_{amb}), the TVS array conducts and clamps the voltage.

Ambient Temperature Adjustment (Tamb=60CT_{amb} = 60^\circ\text{C})

Per Figures 1 and 3 of the Littelfuse AK3 datasheet:

  • Breakdown Voltage Shift (αVBR=+0.088%/C\mathbf{\alpha_{VBR} = +0.088\%\text{/}^\circ\text{C}}):

VBR,single(Tamb)=VBR,single(25C)[1+0.00088(Tamb25C)]V_{BR,single}(T_{amb}) = V_{BR,single}(25^\circ\text{C}) \cdot \left[1 + 0.00088 \cdot (T_{amb} - 25^\circ\text{C})\right]

VBR,single(60C)=620 V[1+0.0008835]=639.1 VV_{BR,single}(60^\circ\text{C}) = 620\text{ V} \cdot \left[1 + 0.00088 \cdot 35\right] = 639.1\text{ V}

  • Peak Pulse Power Derating Factor (kderate\mathbf{k_{derate}}):

kderate(Tamb)={1.0for Tamb50C1.00.005333(Tamb50C)for 50C<Tamb125Ck_{derate}(T_{amb}) = \begin{cases} 1.0 & \text{for } T_{amb} \le 50^\circ\text{C} \\ 1.0 - 0.005333 \cdot (T_{amb} - 50^\circ\text{C}) & \text{for } 50^\circ\text{C} < T_{amb} \le 125^\circ\text{C} \end{cases}

kderate(60C)=1.00.005333×(6050)=0.9467(94.67%)k_{derate}(60^\circ\text{C}) = 1.0 - 0.005333 \times (60 - 50) = 0.9467 \quad (94.67\%)

Array Topology Scaling (Nseries×NparallelN_{series} \times N_{parallel})

For Nseries=2N_{series} = 2 and Nparallel=1N_{parallel} = 1:

VBR,array(60C)=NseriesVBR,single(60C)=2×639.1 V=1278.2 VV_{BR,array}(60^\circ\text{C}) = N_{series} \cdot V_{BR,single}(60^\circ\text{C}) = 2 \times 639.1\text{ V} = 1278.2\text{ V}

Rdyn,array=(NseriesNparallel)Rdyn,single=(21)0.0933 Ω=0.1866 ΩR_{dyn,array} = \left(\frac{N_{series}}{N_{parallel}}\right) \cdot R_{dyn,single} = \left(\frac{2}{1}\right) \cdot 0.0933\ \Omega = 0.1866\ \Omega

Vcl,array(t)=VBR,array(60C)+iTVS(t)Rdyn,arrayV_{cl,array}(t) = V_{BR,array}(60^\circ\text{C}) + i_{TVS}(t) \cdot R_{dyn,array}

Inductor Demagnetization Voltage (VL(t)V_L(t))

By KVL:

VL(t)=VbusVcl,array(t)=1200 V[1278.2 V+iTVS(t)0.1866 Ω]V_L(t) = V_{bus} - V_{cl,array}(t) = 1200\text{ V} - \left[1278.2\text{ V} + i_{TVS}(t) \cdot 0.1866\ \Omega\right]

Because Vcl,array(t)>VbusV_{cl,array}(t) > V_{bus}, VL(t)V_L(t) is negative, demagnetizing the inductor:

diline(t)dt=VL(t)L=Vcl,array(t)VbusL\frac{di_{line}(t)}{dt} = \frac{V_L(t)}{L} = -\frac{V_{cl,array}(t) - V_{bus}}{L}

4. Dynamic Energy Balance & Conservation

The instantaneous stored magnetic energy in the line inductor is:

Einductor(t)=12L[iline(t)]2E_{inductor}(t) = \frac{1}{2} L \cdot \left[i_{line}(t)\right]^2

The cumulative energy delivered by the 1200 V1200\text{ V} DC source during fault clearance is:

Esource(t)=0tVbusiline(τ)dτE_{source}(t) = \int_{0}^{t} V_{bus} \cdot i_{line}(\tau) \, d\tau

The total energy absorbed by the TVS array satisfies energy conservation:

ETVS,total=tclamptclearVcl,array(τ)iTVS(τ)dτ=EL,peak+Esource,demagE_{TVS,total} = \int_{t_{clamp}}^{t_{clear}} V_{cl,array}(\tau) \cdot i_{TVS}(\tau) \, d\tau = E_{L,peak} + E_{source,demag}

ETVS,totalEL,peak(Vcl,avgVcl,avgVbus)E_{TVS,total} \approx E_{L,peak} \cdot \left( \frac{V_{cl,avg}}{V_{cl,avg} - V_{bus}} \right)


Simulation Results Summary

Metric tdet_delay=800 nst_{det\_delay} = 800\text{ ns} tdet_delay=1.0 μst_{det\_delay} = 1.0\ \mu\text{s} tdet_delay=4.0 μst_{det\_delay} = 4.0\ \mu\text{s} tdet_delay=10.0 μst_{det\_delay} = 10.0\ \mu\text{s}
Detection Current (IdetectI_{detect}) 692.0 A692.0\text{ A} 740.0 A740.0\text{ A} 1460.0 A1460.0\text{ A} 2900.0 A2900.0\text{ A}
Peak Line Current (IpeakI_{peak}) 732.0 A732.0\text{ A} 778.8 A778.8\text{ A} 1483.0 A1483.0\text{ A} 2902.4 A2902.4\text{ A}
Peak TVS Clamp Voltage (Vds,maxV_{ds,max}) 1414.4 V1414.4\text{ V} 1423.1 V1423.1\text{ V} 1554.0 V1554.0\text{ V} 1817.4 V1817.4\text{ V}
Peak Inductor Voltage (VL,minV_{L,min}) 214.4 V-214.4\text{ V} 223.1 V-223.1\text{ V} 354.0 V-354.0\text{ V} 617.4 V-617.4\text{ V}
Peak Stored Inductor Energy (EL,peakE_{L,peak}) 1.34 J1.34\text{ J} 1.52 J1.52\text{ J} 5.50 J5.50\text{ J} 21.06 J21.06\text{ J}
Total TVS Array Energy (ETVS,totalE_{TVS,total}) 11.2 J11.2\text{ J} 12.4 J12.4\text{ J} 32.8 J32.8\text{ J} 86.4 J86.4\text{ J}
Per-Diode TVS Energy (ETVS,singleE_{TVS,single}) 5.6 J5.6\text{ J} 6.2 J6.2\text{ J} 16.4 J16.4\text{ J} 43.2 J43.2\text{ J}
Peak TVS Array Power (Ppeak,arrayP_{peak,array}) 1.03 MW1.03\text{ MW} 1.11 MW1.11\text{ MW} 2.30 MW2.30\text{ MW} 5.25 MW5.25\text{ MW}
Per-Diode Peak Power Stress (PsingleP_{single}) 0.52 MW0.52\text{ MW} 0.56 MW0.56\text{ MW} 1.15 MW1.15\text{ MW} 2.63 MW2.63\text{ MW}
Demagnetization Duration (tdemagt_{demag}) 27.8 μs27.8\ \mu\text{s} 28.2 μs28.2\ \mu\text{s} 40.2 μs40.2\ \mu\text{s} 71.4 μs71.4\ \mu\text{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

python
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!

Leave a comment

02d24bb