Exemplo n.º 1
0
def test_fid():
    """
    Test diode current.
    """
    # make sympy symbols
    isat, vd, m, vt = sympy.symbols(['isat', 'vd', 'm', 'vt'])
    # diode current
    id_ = isat * (sympy.exp(vd / m / vt) - 1.0)
    # derivatives
    d_isat = sympy.diff(id_, isat)
    d_vd = sympy.diff(id_, vd)
    d_m = sympy.diff(id_, m)
    d_vt = sympy.diff(id_, vt)
    # evaluate scalars
    test_data1 = {'isat': ISAT_1, 'vd': VD_1, 'm': M_1, 'vt': VT}
    fid_test1, jid_test1 = diode.fid(**test_data1)
    fid_expected1 = np.float(id_.evalf(subs=test_data1))
    jid_expected1 = np.array([
        d_isat.evalf(subs=test_data1),
        d_vd.evalf(subs=test_data1),
        d_m.evalf(subs=test_data1),
        d_vt.evalf(subs=test_data1)
    ],
                             dtype=np.float)
    LOGGER.debug('test: %g = expected: %g', fid_test1, fid_expected1)
    assert np.isclose(fid_test1, fid_expected1)
    assert np.allclose(jid_test1, jid_expected1.reshape(-1, 1))
    # evaluate arrays
    test_data2 = (np.array([ISAT1_2, ISAT2_2]), np.array([VD_1, VD_1]),
                  np.array([1.0, 2.0]), np.array([VT, VT]))
    fid_test2, jid_test2 = diode.fid(*test_data2)
    # lambda functions
    args, math_mod = (isat, vd, m, vt), ("numpy", )
    g_id = sympy.lambdify(args, id_, modules=math_mod)
    g_d_isat = sympy.lambdify(args, d_isat, modules=math_mod)
    g_d_vd = sympy.lambdify(args, d_vd, modules=math_mod)
    g_d_m = sympy.lambdify(args, d_m, modules=math_mod)
    g_d_vt = sympy.lambdify(args, d_vt, modules=math_mod)
    fid_expected2 = g_id(*test_data2)
    jid_expected2 = np.array([
        g_d_isat(*test_data2),
        g_d_vd(*test_data2),
        g_d_m(*test_data2),
        g_d_vt(*test_data2)
    ],
                             dtype=np.float)
    assert np.allclose(fid_test2, fid_expected2)
    assert np.allclose(jid_test2, jid_expected2)
Exemplo n.º 2
0
def residual_two_diode(x, isc, voc, imp, vmp, tc):
    """
    Objective function to solve 2-diode model.
    :param x: parameters isat1, isat2, rs and rsh
    :param isc: short circuit current [A] at tc [C]
    :param voc: open circuit voltage [V] at tc [C]
    :param imp: max power current [A] at tc [C]
    :param vmp: max power voltage [V] at tc [C]
    :param tc: cell temperature [C]
    :return: norm of the residuals its sensitivity
    """
    # Constants
    q = diode.QE  # [C/electron] elementary electric charge
    # (n.b. 1 Coulomb = 1 A * s)
    kb = diode.KB  # [J/K/molecule] Boltzmann's constant
    tck = tc + 273.15  # [K] reference temperature
    # Governing Equation
    vt = kb * tck / q  # [V] thermal voltage
    # Rescale Variables
    isat1_t0 = np.exp(x[0])
    isat2 = np.exp(x[1])
    rs = x[2]**2.0
    rsh = x[3]**2.0
    # first diode saturation current
    isat1 = diode.isat_t(tc, isat1_t0)
    # Short Circuit
    vd_isc, _ = diode.fvd(vc=0.0, ic=isc, rs=rs)
    id1_isc, _ = diode.fid(isat=isat1, vd=vd_isc, m=1.0, vt=vt)
    id2_isc, _ = diode.fid(isat=isat2, vd=vd_isc, m=2.0, vt=vt)
    ish_isc, _ = diode.fish(vd=vd_isc, rsh=rsh)
    # Photo-generated Current
    iph = isc + id1_isc + id2_isc + ish_isc  # [A]
    # Open Circuit
    vd_voc, jvd_voc = diode.fvd(vc=voc, ic=0.0, rs=rs)
    id1_voc, jid1_voc = diode.fid(isat=isat1, vd=vd_voc, m=1.0, vt=vt)
    id2_voc, jid2_voc = diode.fid(isat=isat2, vd=vd_voc, m=2.0, vt=vt)
    ish_voc, jish_voc = diode.fish(vd=vd_voc, rsh=rsh)
    # Max Power Point
    vd_mpp, jvd_mpp = diode.fvd(vc=vmp, ic=imp, rs=rs)
    id1_mpp, jid1_mpp = diode.fid(isat=isat1, vd=vd_mpp, m=1.0, vt=vt)
    id2_mpp, jid2_mpp = diode.fid(isat=isat2, vd=vd_mpp, m=2.0, vt=vt)
    ish_mpp, jish_mpp = diode.fish(vd=vd_mpp, rsh=rsh)
    # Slope at Max Power Point
    dpdv, jdpdv = two_diode.fdpdv(isat1=isat1,
                                  isat2=isat2,
                                  rs=rs,
                                  rsh=rsh,
                                  ic=imp,
                                  vc=vmp,
                                  vt=vt)
    # Shunt Resistance
    frsh, jrsh = two_diode.fjrsh(isat1=isat1,
                                 isat2=isat2,
                                 rs=rs,
                                 rsh=rsh,
                                 vt=vt,
                                 isc=isc)
    # Residual
    # should be (M, ) array with M residual equations (constraints)
    f2 = np.stack(
        [
            (iph - id1_voc - id2_voc - ish_voc).T,  # Open Circuit
            (iph - id1_mpp - id2_mpp - ish_mpp - imp).T,  # Max Power Point
            dpdv.T,  # Slope at Max Power Point
            frsh.T  # Shunt Resistance
        ],
        axis=0).flatten()
    # Jacobian
    # should be (M, N) array with M residuals and N variables
    # [[df1/dx1, df1/dx2, ...], [df2/dx1, df2/dx2, ...]]
    jvoc = np.stack(
        (
            -jid1_voc[0],  # d/disat1
            -jid2_voc[0],  # d/disat2
            -jvd_voc[2] * (jid1_voc[1] + jid2_voc[1] + jish_voc[0]),  # d/drs
            -jish_voc[1]  # d/drsh
        ),
        axis=0).T.reshape(-1, 4)
    jmpp = np.stack(
        (
            -jid1_mpp[0],  # d/disat1
            -jid2_mpp[0],  # d/disat2
            -jvd_mpp[2] * (jid1_mpp[1] + jid2_mpp[1] + jish_mpp[0]),  # d/drs
            -jish_mpp[1]  # d.drsh
        ),
        axis=0).T.reshape(-1, 4)
    # Scaling Factors
    scale_fx = np.array([np.exp(x[0]), np.exp(x[1]), 2 * x[2], 2 * x[3]])
    # scales each column by the corresponding element
    j2 = np.concatenate(
        (jvoc, jmpp, jdpdv[:4].T.reshape(-1, 4), jrsh[:4].T.reshape(-1, 4)),
        axis=0) * scale_fx
    return f2, j2