Ejemplo n.º 1
0
def find_steady_state(tfwd, ckt, t12min=500e-9, fswmax=100e3):
    # print(f'finding steady-state for tfwd={fmt(tfwd)}s...')
    def eq(v0):
        # print(f'  trying from v0={fmt(v0, 4)}V')
        dv, ss = sim(v0, ckt, (tfwd, t12min))
        fsw = 1 / sum(s.dt for s in ss)
        if fsw > fswmax:

            def eqf(t12):
                _, ss = sim(v0, ckt, (tfwd, t12))
                fsw = 1 / sum(s.dt for s in ss)
                return fsw - fswmax

            t12 = nsolve(eqf, t12min, 1 / fswmax)
            dv, ss = sim(v0, ckt, (tfwd, t12))
        return dv, ss

    eq(75.16256356353576)  # FIXME: delete
    v0max = ckt.vbus
    v0min = -ckt.vout / ckt.lm * (ckt.lr + ckt.lm)
    v0 = nsolve(lambda v: eq(v)[0], v0min * .99 + v0max * .01,
                v0max * .99 + v0min * .01)
    residue, ss = eq(v0)

    if abs(residue) > MINIMUM_VOLTAGE:
        print(f'Warning: cannot find steady-state for tfwd = {fmt(tfwd)}s.')
    return ss
Ejemplo n.º 2
0
def test_case_01():
    ckt = ahbllc.AHBLLCTrafo(lr=25e-6, lm=1225e-6, cr=39e-9, nps=4.3, vbus=410, vload=20, chb=500e-12)
    con = 200e-9
    v0 = nsolve(lambda v: ahbllc.sim(v, ckt, (con, 500e-9))[0], -ckt.vbus, ckt.vout / ckt.lm * (ckt.lr + ckt.lm))
    _, ss = ahbllc.sim(v0, ckt, (con, 500e-9))
    fig, *_ = plot(ss, show=True)
    ev = ahbllc.evaluate_switching_period(ss)
    print(ev.set_circuit(ckt))
    plt.close(fig)
Ejemplo n.º 3
0
def sim(v0, ckt, con):
    commutating = lambda s: s in {state_c0, state_c1}
    active = lambda s: s not in {state_c0, state_c1}

    def max_dv(i0, v0):
        l = ckt.lr + ckt.lm
        c = 1 / (1 / ckt.cr + 1 / ckt.chb)
        z = (l / c)**.5
        r = math.hypot(v0, i0 * z)
        phi = math.atan2(v0, i0 * z)
        return r * (1 + math.sin(phi))

    def eq_zvon(t):
        _, ls_on = _sim_phase(ls_on_inf, active, hs_off[-1].i1, hs_off[-1].v1,
                              hs_off[-1].vhb1, hs_off[-1].im1, ckt, t)
        return max_dv(ls_on[-1].i1,
                      ls_on[-1].v1) - (1 + ckt.chb / ckt.cr) * ckt.vbus

    conv, t12min = con
    i0 = 0
    vhb0 = ckt.vbus

    # high-side on phase
    nsf, hs_on = _sim_phase(state_h0, active, i0, v0, vhb0, i0, ckt, conv)

    # high-side off phase
    ls_on_inf, hs_off = _sim_phase(nsf, commutating, hs_on[-1].i1,
                                   hs_on[-1].v1, hs_on[-1].vhb1, hs_on[-1].im1,
                                   ckt, None)

    # low-side on phase
    _, ls_on = _sim_phase(ls_on_inf, active, hs_off[-1].i1, hs_off[-1].v1,
                          hs_off[-1].vhb1, hs_off[-1].im1, ckt, t12min)
    if max_dv(ls_on[-1].i1, ls_on[-1].v1) < (1 + ckt.chb / ckt.cr) * ckt.vbus:
        t12max = (math.pi - ls_on[-1].phi) / ls_on[-1].w
        if t12min < t12max <= MAXIMUM_T12:
            if 0 < eq_zvon(t12max):
                t12_zvon = nsolve(eq_zvon, t12min, t12max)
            else:
                t12_zvon = t12max
            _, ls_on = _sim_phase(ls_on_inf, active, hs_off[-1].i1,
                                  hs_off[-1].v1, hs_off[-1].vhb1,
                                  hs_off[-1].im1, ckt, t12_zvon)

    # low-side off phase
    _, ls_off = _sim_phase(state_c0, commutating, ls_on[-1].i1, ls_on[-1].v1,
                           ls_on[-1].vhb1, ls_on[-1].im1, ckt, None)

    # high-side on phase
    _, hs_on2 = _sim_phase(state_h0, active, ls_off[-1].i1, ls_off[-1].v1,
                           ls_off[-1].vhb1, ls_off[-1].im1, ckt, None)

    return hs_on2[-1].v1 - v0, hs_on + hs_off + ls_on + ls_off + hs_on2
Ejemplo n.º 4
0
def evaluate_operating_point(pout, ckt, t12min=500e-9, fswmax=100e3):
    pmax = evaluate_switching_period(
        find_steady_state(ckt.vbus, ckt, t12min, fswmax)).iout * ckt.vout
    if 0 < pout <= pmax:
        voff = nsolve(
            lambda v: evaluate_switching_period(
                find_steady_state(v, ckt, t12min, fswmax)).iout * ckt.vout -
            pout, ckt.vout / 10, ckt.vbus)
        ss = find_steady_state(voff, ckt, t12min, fswmax)
        return voff, ss, evaluate_switching_period(ss)
    else:
        return 0, [State()], Evaluation()
Ejemplo n.º 5
0
    def eq(v0):
        # print(f'  trying from v0={fmt(v0, 4)}V')
        dv, ss = sim(v0, ckt, (tfwd, t12min))
        fsw = 1 / sum(s.dt for s in ss)
        if fsw > fswmax:

            def eqf(t12):
                _, ss = sim(v0, ckt, (tfwd, t12))
                fsw = 1 / sum(s.dt for s in ss)
                return fsw - fswmax

            t12 = nsolve(eqf, t12min, 1 / fswmax)
            dv, ss = sim(v0, ckt, (tfwd, t12))
        return dv, ss
Ejemplo n.º 6
0
def state_h0_vincscomp(i0, v0, vhb0, im0, ckt, con, state_func_list):
    """Sub-state of:
    h - high-side device on,
    0 - output rectifier off.

    Exit criteria: high-side turned off when v reaches voff

    vincscomp - voltage increment control with slope compensation
    """
    del vhb0, im0
    dvoff = con

    chb = math.inf
    cr = ckt.cr
    ctot = 1 / (1 / cr + 1 / chb)
    ltot = ckt.lr + ckt.lm
    w = (ltot * ctot)**-.5
    z = (ltot / ctot)**.5

    vhb0 = ckt.vbus
    vout = 0
    vcen = vhb0 + vout
    r = math.hypot(v0 - vcen, i0 * z)
    phi = math.atan2(v0 - vcen, i0 * z)
    # i = r * cos(w * t + phi) / z
    # v = r * sin(w * t + phi) + vcen
    # vhb = vbus
    # im = i

    slope = 40 / 10e-6
    if i0 == 0:
        # v0 + dvoff - slope * t == r * sin(w * t + phi) + vcen
        dt = nsolve(
            lambda t: v0 + dvoff - slope * t - r * math.sin(w * t + phi) -
            vcen, 0, math.pi / w)
        # dt = min((math.asin((v0 + dvoff - vcen) / r) - phi) % (2 * math.pi),
        #          (math.pi - math.asin((v0 + dvoff - vcen) / r) - phi) % (2 * math.pi)) / w
    else:
        # 0 = r * cos(w * t + phi) / z, w * t + phi = -pi / 2
        dt = ((-math.pi / 2 - phi) % (2 * math.pi)) / w
    i1 = r * math.cos(w * dt + phi) / z
    v1 = r * math.sin(w * dt + phi) + vcen

    next_state = state_func_list['state_c0']
    return next_state, State(state='h0', dt=dt,
                             i0=i0, v0=v0, vhb0=vhb0, im0=i0,
                             i1=i1, v1=v1, vhb1=vhb0, im1=i1,
                             r=r, phi=phi, w=w, z=z,
                             cr=cr, chb=chb,
                             vcen=vcen, vout=vout, km=0) # yapf: disable
Ejemplo n.º 7
0
    def eq(i):
        di, _, ss = sim(i, ckt, (voff, t12min))
        fsw = 1 / sum(s.dt for s in ss)
        if fsw > fswmax:

            def eqf(t):
                _, _, ss = sim(i, ckt, (voff, t))
                fsw = 1 / sum(s.dt for s in ss)
                return fsw - fswmax

            t12 = nsolve(eqf, .5e-6, 1 / fswmax)
            di, _, ss = sim(i, ckt, (voff, t12))
        dv = ss[-1].v1 - voff
        return di, dv, ss
Ejemplo n.º 8
0
def state_l1(i0, v0, vhb0, im0, ckt, con):
    """Sub-state of:
    l - low-side device on,
    1 - output rectifier on.

    Exit criteria: resonant current == magnetizing current (solve the Kepler's Equation)
    """
    del vhb0, con  # vhb == 0

    chb = math.inf
    cr = ckt.cr
    ctot = 1 / (1 / cr + 1 / chb)
    ltot = ckt.lr
    w = (ltot * ctot)**-.5
    z = (ltot / ctot)**.5
    km = ckt.vout / ckt.lm

    vhb0 = 0
    vout = ckt.vout
    vcen = vhb0 + vout
    r = math.hypot(v0 - vcen, i0 * z)
    phi = math.atan2(v0 - vcen, i0 * z)
    # i = r * cos(w * t + phi) / z
    # v = r * sin(w * t + phi) + vcen
    # vhb = 0
    # im = im0 - km * t

    ta = tb = (-phi % (2 * math.pi)) / w
    while r * math.cos(w * ta + phi) / z > im0 - km * ta and ta > MINIMUM_TIME:
        ta /= 2
    if ta > MINIMUM_TIME:
        dt = nsolve(lambda t: im0 - km * t - r * math.cos(w * t + phi) / z, ta,
                    tb)
    else:
        dt = ta
    i1 = r * math.cos(w * dt + phi) / z
    v1 = r * math.sin(w * dt + phi) + vout
    next_state = state_l0
    return next_state, State(state='l1', dt=dt,
                             i0=i0, v0=v0, vhb0=vhb0, im0=im0,
                             i1=i1, v1=v1, vhb1=vhb0, im1=i1,
                             r=r, phi=phi, w=w, z=z,
                             cr=cr, chb=chb,
                             vcen=vcen, vout=vout, km=-km) # yapf: disable
Ejemplo n.º 9
0
def evaluate_operating_point(pout, ckt, t12min=500e-9, fswmax=100e3):
    # tfwdmax = math.pi / 2 / ((ckt.lr + ckt.lm) * ckt.cr)**-.5
    vdion = ckt.vout / ckt.lm * (ckt.lr + ckt.lm)
    tfwdmax = (math.pi / 2 + math.asin(vdion / (ckt.vbus + vdion))) / (
        (ckt.lr + ckt.lm) * ckt.cr)**-.5
    sspmax = find_steady_state(tfwdmax, ckt, t12min, fswmax)
    pmax = evaluate_switching_period(sspmax).iout * ckt.vout
    if 0 < pout <= pmax:
        evaluate_switching_period(
            find_steady_state(MINIMUM_FORWARD_TIME, ckt, t12min,
                              fswmax))  # FIXME: debug only
        tf = nsolve(
            lambda t: evaluate_switching_period(
                find_steady_state(t, ckt, t12min, fswmax)).iout * ckt.vout -
            pout, MINIMUM_FORWARD_TIME, tfwdmax)
        ss = find_steady_state(tf, ckt, t12min, fswmax)
        return tf, ss, evaluate_switching_period(ss), pmax
    else:
        return 0, [State()], Evaluation(), pmax
Ejemplo n.º 10
0
def find_steady_state(voff, ckt, t12min=500e-9, fswmax=100e3):
    def eq(i):
        di, _, ss = sim(i, ckt, (voff, t12min))
        fsw = 1 / sum(s.dt for s in ss)
        if fsw > fswmax:

            def eqf(t):
                _, _, ss = sim(i, ckt, (voff, t))
                fsw = 1 / sum(s.dt for s in ss)
                return fsw - fswmax

            t12 = nsolve(eqf, .5e-6, 1 / fswmax)
            di, _, ss = sim(i, ckt, (voff, t12))
        dv = ss[-1].v1 - voff
        return di, dv, ss

    i0max = ckt.vbus / ((ckt.lr + ckt.lm) / ckt.cr)**.5
    i0 = nsolve(lambda i: eq(i)[0], .001, i0max * 2)
    _, _, ss = eq(i0)
    return ss
Ejemplo n.º 11
0
def state_c1(i0, v0, vhb0, im0, ckt, con):
    """Sub-state of:
    c - both devices are off, half-bridge behaving like a capacitor,
    1 - output rectifier on.
    This state occurs when
      1) we consider the commutation, and
      2) in heavy load where the output diode turns on immediately after the turning-off of the high-side MOS.

    Exit criteria:
      (1) half-bridge voltage reaches DC bus or 0 --> h1 (prevented in control strategy) or l1
      (2) Exit criteria: resonant current == magnetizing current (solve the Kepler's Equation) --> c0
          very unlikely to happen (but it's *not* impossible, consider the condition where Lm is extremely small)
    """
    del con

    chb = ckt.chb
    cr = ckt.cr
    ctot = 1 / (1 / cr + 1 / chb)
    ltot = ckt.lr
    w = (ltot * ctot)**-.5
    z = (ltot / ctot)**.5

    vcen = vout = ckt.vout
    vcap0 = v0 - vhb0
    r = math.hypot(vcap0 - vcen, i0 * z)
    phi = math.atan2(vcap0 - vcen, i0 * z)
    km = ckt.vout / ckt.lm
    # i(t) == r * cos(w * t + phi) / z, resonant current
    #   i(0) == i0 <= 0, guaranteed by previous state
    # vcap(t) = r * sin(w * t + phi) + vcen, voltage across two capacitors
    # v(t) == r * sin(w * t + phi) / (1 + cr / chb) +
    #         v0 / (1 + chb / cr) +
    #         (vhb0 + vout) / (1 + cr / chb)
    # vhb(t) == -r * sin(w * t + phi) / (1 + chb / cr) -
    #           (vout - v0) / (1 + chb / cr) +
    #           vhb0 / (1 + cr / chb)

    v = 0  # target of the resonant voltage v
    v -= -(vout - v0) / (1 + chb / cr) + vhb0 / (1 + cr / chb)
    v *= (1 + chb / cr)
    if -r <= v <= r:
        dtcomm = min((math.asin(v / -r) - phi) % (2 * math.pi),
                     (math.pi - math.asin(v / -r) - phi) % (2 * math.pi)) / w
    else:  # hard-switching, which is allowed
        dtcomm = (math.pi / 2 - phi) % (2 * math.pi) / w

    ta = tb = (-phi % (2 * math.pi)) / w
    while r * math.cos(w * ta + phi) / z > im0 - km * ta and ta > MINIMUM_TIME:
        ta /= 2
    if ta > MINIMUM_TIME:
        dtdiof = nsolve(lambda t: im0 - km * t - r * math.cos(w * t + phi) / z,
                        ta, tb)
    else:
        dtdiof = ta

    if dtdiof < dtcomm:  # diode turns off before commutation finishes (vhb reduces to 0), almost impossible
        dt = dtdiof
        next_state = state_c0
    else:
        dt = dtcomm
        next_state = state_l1

    i1 = r * math.cos(w * dt + phi) / z
    v1 = (r * math.sin(w * dt + phi) / (1 + cr / chb) + v0 / (1 + chb / cr) +
          (vhb0 + vout) / (1 + cr / chb))
    vhb1 = (-r * math.sin(w * dt + phi) / (1 + chb / cr) - (vout - v0) /
            (1 + chb / cr) + vhb0 / (1 + cr / chb))
    if -1e-6 < vhb1 - ckt.vbus < 1e-6:
        vhb1 = ckt.vbus
    elif -1e-6 < vhb1 < 1e-6:
        vhb1 = 0
    im1 = im0 - km * dt
    if -1e-6 < im1 - i1 < 1e-6:
        im1 = i1

    return next_state, State(state='c1', dt=dt,
                             i0=i0, v0=v0, vhb0=vhb0, im0=im0,
                             i1=i1, v1=v1, vhb1=vhb1, im1=im1,
                             r=r, phi=phi, w=w, z=z,
                             cr=cr, chb=chb,
                             vcen=vcen, vout=vout, km=-km) # yapf: disable
Ejemplo n.º 12
0
def sim_voff(i0, ckt, con):
    sfl = dict(state_l1=state_l1,
               state_l0=state_l0,
               state_h0=state_h0_voff,
               state_c0=state_c0,
               state_c1=state_c1)
    commutating = lambda s: s in {sfl['state_c0'], sfl['state_c1']}
    active = lambda s: s not in {sfl['state_c0'], sfl['state_c1']}

    def eq_zvon(t, hs_off_fins):
        # from the end moment of the high-side turning-off state (high- to low-side commutation finishes),
        # find out what t12 gives ZV-on of the high-side device.
        _, ss = _sim_phase(isf_ls_on, active, *hs_off_fins, ckt, t, sfl)
        ls_on_fins = (ss[-1].i1, ss[-1].v1, ss[-1].vhb1, ss[-1].im1)
        _, ss = _sim_phase(state_c0, commutating, *ls_on_fins, ckt, t, sfl)
        c0 = ss[-1]
        r, chb, cr = c0.r, c0.chb, c0.cr
        vout, v0, vhb0 = c0['vout'], c0.v0, c0.vhb0
        vhbmax = r / (1 + chb / cr) - (vout - v0) / (1 + chb / cr) + vhb0 / (
            1 + cr / chb)
        return vhbmax - ckt.vbus

    # def eq_vcont(t, hs_off_fins, ratio_v_ls_on=.95):
    #     # resonant voltage continuity equation:
    #     # t should be so long that when we turn off the low-side,
    #     # v the resonant voltage is at (or below) ratio_v_ls_on * voff
    #     _, ss = _sim1(isf_ls_on, active, *hs_off_fins, ckt, t)
    #     v_ls_on_fin = ss[-1].v1
    #     return v_ls_on_fin - voff * ratio_v_ls_on

    # def eq_vcont(t, hs_off_fins, ratio_v_ls_on=.95):
    #     # resonant voltage continuity equation:
    #     # t should be so long that when we turn off the low-side and go into the high-side on state,
    #     # the minimum value of v, the resonant voltage, is at (or below) ratio_v_ls_on * voff
    #     # 这样做看起来很理想,但是
    #     #   1) 无法实现,除非控制器有办法得知 hs_on 状态中 v 的最小值
    #     #   2) 会改变 sim 返回值 i_fin - i0 随 i0 的单调性,使方程无法可靠求解
    #     _, ss = _sim1(isf_ls_on, active, *hs_off_fins, ckt, t)
    #     ls_on_fins = (ss[-1].i1, ss[-1].v1, ss[-1].vhb1, ss[-1].im1)
    #     _, ss = _sim1(state_c0, commutating, *ls_on_fins, ckt, t)
    #     v0 = ss[-1].v1
    #     i0 = ss[-1].i1
    #     z = ((ckt.lr + ckt.lm) / ckt.cr)**.5
    #     vcen = ckt.vbus
    #     r = math.hypot(v0 - vcen, i0 * z)
    #     vmin = -r + vcen
    #     return vmin - voff * ratio_v_ls_on

    voff, t12min = con
    # starting at the turning-off moment of the high-side device
    v0 = voff
    vhb0 = ckt.vbus

    # high-side turning-off phase
    nsf, hs_off = _sim_phase(state_c0, commutating, i0, v0, vhb0, i0, ckt,
                             None, sfl)
    hs_off_fins = (hs_off[-1].i1, hs_off[-1].v1, hs_off[-1].vhb1,
                   hs_off[-1].im1)

    isf_ls_on = nsf  # remember the initial state of the low-side on phase,
    # we may needed repetitively in determine t12 for high-side ZV-on
    # low-side on phase
    nsf, ls_on = _sim_phase(isf_ls_on, active, *hs_off_fins, ckt, t12min, sfl)
    ls_on_fins = (ls_on[-1].i1, ls_on[-1].v1, ls_on[-1].vhb1, ls_on[-1].im1)
    t12capm = ls_on[
        -1].dt  # state_l0 automatically increases t12 and avoids capactive mode
    # low-side turning-off phase
    nsf, ls_off = _sim_phase(state_c0, commutating, *ls_on_fins, ckt, None,
                             sfl)
    ls_off_fins = (ls_off[-1].i1, ls_off[-1].v1, ls_off[-1].vhb1,
                   ls_off[-1].im1)

    # correct t12
    t12zvon = 0
    t12max = (math.pi - ls_on[-1].phi) / ls_on[
        -1].w  # the t12 that generates the most negative current before low-side turns off
    if ls_off[
            -1].vhb1 < ckt.vbus - MINIMUM_VOLTAGE:  # hard-switching occurs, see if we can avoid it
        if eq_zvon(t12max, hs_off_fins) >= 0:  # yes, we can
            t12zvon = nsolve(lambda t: eq_zvon(t, hs_off_fins), t12min / 2,
                             t12max)
        else:  # hard-switching we cannot avoid, in conditions, e.g., too much chb
            t12zvon = t12max
    t12 = max(t12min, t12capm, t12zvon)
    # t12vcont = 0  # in practice, the switching frequency is limited
    # if ls_off[-1].v1 > voff:
    #     t12vcont = nsolve(lambda t: eq_vcont(t, hs_off_fins), t12min / 2, t12max)
    # t12 = max(t12, t12vcont)

    # t12 correction needed
    if t12 > t12min:  # re-run the low-side on and low- to high-side commutation
        nsf, ls_on = _sim_phase(isf_ls_on, active, *hs_off_fins, ckt, t12, sfl)
        ls_on_fins = (ls_on[-1].i1, ls_on[-1].v1, ls_on[-1].vhb1,
                      ls_on[-1].im1)
        nsf, ls_off = _sim_phase(state_c0, commutating, *ls_on_fins, ckt, None,
                                 sfl)
        ls_off_fins = (ls_off[-1].i1, ls_off[-1].v1, ls_off[-1].vhb1,
                       ls_off[-1].im1)

    # high-side on phase
    _, hs_on = _sim_phase(state_h0_voff, active, *ls_off_fins, ckt, voff, sfl)
    res = hs_on[-1].i1 - i0
    if hs_on[-1].v1 > voff + MINIMUM_VOLTAGE:
        dt_ls_off = sum(s.dt for s in ls_off)
        dt_hs_on = MAXIMUM_COMMUTATION_TIME - dt_ls_off
        if dt_hs_on < MINIMUM_HIGH_SIDE_ON_TIME:
            dt_hs_on = MINIMUM_HIGH_SIDE_ON_TIME
        hs_on_v0 = ls_off[-1].v1
        hs_on_i0 = ls_off[-1].i1
        hs_on_z = ((ckt.lr + ckt.lm) / ckt.cr)**.5
        hs_on_w = ((ckt.lr + ckt.lm) * ckt.cr)**-.5
        hs_on_vcen = ckt.vbus
        hs_on_r = math.hypot(hs_on_v0 - hs_on_vcen, hs_on_i0 * hs_on_z)
        hs_on_phi = math.atan2(hs_on_v0 - hs_on_vcen, hs_on_i0 * hs_on_z)
        hs_on_v1 = hs_on_r * math.sin(hs_on_w * dt_hs_on +
                                      hs_on_phi) + hs_on_vcen
        _, hs_on = _sim_phase(state_h0_voff, active, *ls_off_fins, ckt,
                              hs_on_v1)
        # voltage continuity violates if we reach here, which indicates that
        # the i_fin - i0 function could have multiple zeros, and the solver may fail.
        # consider changing the res to keep it monotone
        res = hs_on[-1].i1 - i0

    states = hs_off + ls_on + ls_off + hs_on
    return res, t12, states  # TODO: 统一所有 simulator 的返回格式
Ejemplo n.º 13
0
def sim_dvoff(i0, v0, ckt, con):
    """Simulator used only for delta-V turning-off control.
    The first return variable is a tuple of two floats
    representing the residue current and voltage.

    :param i0: initial current
    :type i0: float
    :param v0: initial voltage
    :type v0: float
    :param ckt: circuit
    :type ckt: AHBLLC
    :param con: controlling variable
    :type con: tuple of two floats
    :return: residues and states
    :rtype: Tuple[residues, states] where residues::Tuple[float, float], states::State
    """
    sfl = dict(state_l1=state_l1,
               state_l0=state_l0,
               state_h0=state_h0_dvoff,
               state_c0=state_c0,
               state_c1=state_c1)
    commutating = lambda s: s in {sfl['state_c0'], sfl['state_c1']}
    active = lambda s: s not in {sfl['state_c0'], sfl['state_c1']}

    def max_dv(i0, v0):
        l = ckt.lr + ckt.lm
        c = 1 / (1 / ckt.cr + 1 / ckt.chb)
        z = (l / c)**.5
        r = math.hypot(v0, i0 * z)
        phi = math.atan2(v0, i0 * z)
        return r * (1 + math.sin(phi))

    def eq_zvon(t):
        _, ls_on = _sim_phase(ls_on_inf, active, hs_off[-1].i1, hs_off[-1].v1,
                              hs_off[-1].vhb1, hs_off[-1].im1, ckt, t, sfl)
        return max_dv(ls_on[-1].i1,
                      ls_on[-1].v1) - (1 + ckt.chb / ckt.cr) * ckt.vbus

    dvoff, t12min = con
    vhb0 = ckt.vbus

    # high-side on phase
    nsf, hs_on = _sim_phase(state_h0_dvoff, active, i0, v0, vhb0, i0, ckt,
                            dvoff, sfl)

    # high-side off phase
    ls_on_inf, hs_off = _sim_phase(nsf, commutating, hs_on[-1].i1,
                                   hs_on[-1].v1, hs_on[-1].vhb1, hs_on[-1].im1,
                                   ckt, None, sfl)

    # low-side on phase
    _, ls_on = _sim_phase(ls_on_inf, active, hs_off[-1].i1, hs_off[-1].v1,
                          hs_off[-1].vhb1, hs_off[-1].im1, ckt, t12min, sfl)
    if max_dv(ls_on[-1].i1, ls_on[-1].v1) < (1 + ckt.chb / ckt.cr) * ckt.vbus:
        t12max = (math.pi - ls_on[-1].phi) / ls_on[-1].w
        if t12min < t12max:
            if 0 < eq_zvon(t12max):
                t12_zvon = nsolve(eq_zvon, t12min, t12max)
            else:
                t12_zvon = t12max
            _, ls_on = _sim_phase(ls_on_inf, active, hs_off[-1].i1,
                                  hs_off[-1].v1, hs_off[-1].vhb1,
                                  hs_off[-1].im1, ckt, t12_zvon, sfl)

    # low-side off phase
    _, ls_off = _sim_phase(state_c0, commutating, ls_on[-1].i1, ls_on[-1].v1,
                           ls_on[-1].vhb1, ls_on[-1].im1, ckt, None, sfl)

    return (ls_off[-1].i1 - i0,
            ls_off[-1].v1 - v0), hs_on + hs_off + ls_on + ls_off
Ejemplo n.º 14
0
def sim(v0, ckt, con, constr=None):
    sfl = dict(state_l1=state_l1,
               state_l0=state_l0,
               state_h0=state_h0_tfwd,
               state_c0=state_c0,
               state_c1=state_c1)
    if constr is not None:
        sfl['state_h0'] = constr
    assert v0 < ckt.vbus
    commutating = lambda s: s in {sfl['state_c0'], sfl['state_c1']}
    active = lambda s: s not in {sfl['state_c0'], sfl['state_c1']}

    def max_dv(i0, v0):
        l = ckt.lr + ckt.lm
        c = 1 / (1 / ckt.cr + 1 / ckt.chb)
        z = (l / c)**.5
        r = math.hypot(v0, i0 * z)
        phi = math.atan2(v0, i0 * z)
        return r * (1 + math.sin(phi))

    def eq_zvon(t):
        _, ls_on = _sim_phase(ls_on_inf, active, hs_off[-1].i1, hs_off[-1].v1,
                              hs_off[-1].vhb1, hs_off[-1].im1, ckt, t, sfl)
        return max_dv(ls_on[-1].i1,
                      ls_on[-1].v1) - (1 + ckt.chb / ckt.cr) * ckt.vbus

    conv, t12min = con
    i0 = 0
    vhb0 = ckt.vbus

    # high-side on phase
    nsf, hs_on = _sim_phase(sfl['state_h0'], active, i0, v0, vhb0, i0, ckt,
                            conv, sfl)

    # high-side off phase
    ls_on_inf, hs_off = _sim_phase(nsf, commutating, hs_on[-1].i1,
                                   hs_on[-1].v1, hs_on[-1].vhb1, hs_on[-1].im1,
                                   ckt, None, sfl)

    # low-side on phase
    _, ls_on = _sim_phase(ls_on_inf, active, hs_off[-1].i1, hs_off[-1].v1,
                          hs_off[-1].vhb1, hs_off[-1].im1, ckt, t12min, sfl)
    if max_dv(ls_on[-1].i1, ls_on[-1].v1) < (1 + ckt.chb / ckt.cr) * ckt.vbus:
        t12max = (math.pi - ls_on[-1].phi) / ls_on[-1].w
        if t12min < t12max:
            if 0 < eq_zvon(t12max):
                t12_zvon = nsolve(eq_zvon, t12min, t12max)
            else:
                t12_zvon = t12max
            _, ls_on = _sim_phase(ls_on_inf, active, hs_off[-1].i1,
                                  hs_off[-1].v1, hs_off[-1].vhb1,
                                  hs_off[-1].im1, ckt, t12_zvon, sfl)

    # low-side off phase
    _, ls_off = _sim_phase(sfl['state_c0'], commutating, ls_on[-1].i1,
                           ls_on[-1].v1, ls_on[-1].vhb1, ls_on[-1].im1, ckt,
                           None, sfl)

    # high-side on phase
    _, hs_on2 = _sim_phase(sfl['state_h0'], active, ls_off[-1].i1,
                           ls_off[-1].v1, ls_off[-1].vhb1, ls_off[-1].im1, ckt,
                           None, sfl)

    return hs_on2[-1].v1 - v0, hs_on + hs_off + ls_on + ls_off + hs_on2