Пример #1
0
    def test_series_connected_mj_cells(self):
        """
        Test three series-connected triple-junction cells.
        We break them down into nine series-connected subcells and perform ```solve_series_connected_ivs()```

        :return:
        """
        sq1_cell = SQCell(eg=1.87, cell_T=300, plug_in_term=rev_diode)

        sq2_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=rev_diode)

        sq3_cell = SQCell(eg=1.0, cell_T=300, plug_in_term=rev_diode)

        tj_cell = MJCell([sq1_cell, sq2_cell, sq3_cell])
        tj_cell.set_input_spectrum(load_astm(("AM1.5d")))

        # Set up the MJCell() first. The purpose is only for calculating the transmitted spectrum
        # and the photocurrent of each subcell. We don't use the MJCell.get_j_from_v() to solve the I-V
        connected_cells = []
        number_of_mjcell = 3

        multi = np.array([0, 0.25, 0.5])
        for i in range(number_of_mjcell):
            # Need copy.deepcopy to also copy the subcells
            c_tj_cell = copy.deepcopy(tj_cell)
            # multi = np.random.random() * 0.5

            c_tj_cell.set_input_spectrum(load_astm("AM1.5d") * (1 + multi[i]))
            connected_cells.append(c_tj_cell)

        # Extract each subcell, make them into series-connected cells
        # Connect all the subcells in series
        iv_funcs = []
        for mj_cells in connected_cells:
            for subcell in mj_cells.subcell:
                iv_funcs.append(subcell.get_j_from_v)

        reverse_plot = True

        if reverse_plot:
            rev_fac = -1
        else:
            rev_fac =1

        from pypvcell.fom import isc
        for idx, cell in enumerate(connected_cells):
            v, i = cell.get_iv()
            print(isc(v, i * rev_fac))
            plt.plot(v, i * rev_fac, label="MJ cell {}".format(idx + 1))

        iv_pair = solve_series_connected_ivs(iv_funcs, vmin=-1, vmax=3.5, vnum=300)

        plt.plot(iv_pair[0], iv_pair[1] * rev_fac, '.-', label="Connected I-V")
        plt.ylim(sorted([-300 * rev_fac, 0]))
        plt.xlim([-10, 12])
        plt.xlabel("voltage (V)")
        plt.ylabel("current (A/m^2)")
        plt.legend()
        plt.savefig("./tests_output/Mjx3_demo.png", dpi=300)
        plt.show()
    def test_diode_solver(self):
        hp1 = HighPSQCell(1.42, cell_T=300)
        hp1.set_input_spectrum(load_astm())

        hp2 = HighPSQCell(1.42, cell_T=300)
        hp2.set_input_spectrum(load_astm())

        hp3 = HighPSQCell(1.42, cell_T=300)
        hp3.set_input_spectrum(load_astm())

        ref_hp = HighPSQCell(1.42, cell_T=300)
        ref_hp.set_input_spectrum(load_astm())

        d1 = DiodeSeriesConnect([hp1, hp2, hp3])

        test_v = 1.0
        j1 = d1.get_j_from_v(test_v)
        j2 = ref_hp.get_j_from_v(test_v / 3.0)
        # by circuit law, j1 should equal to j2

        self.assertTrue(np.isclose(j1, j2))

        # extend the examination range

        test_v = np.linspace(-1, 1, 10)
        j1 = d1.get_j_from_v(test_v)
        j2 = ref_hp.get_j_from_v(test_v / 3.0)

        self.assertTrue(np.allclose(j1, j2))
Пример #3
0
    def test_parallel_connected_mj_cells_2(self):
        """
        Try connecting two strings of cells. All are Eg=1.42 SQCell.
        Each string has five cells. One string has a cell has only 0.5 sun.

        :return:
        """

        normal_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=rev_diode)
        normal_cell.set_input_spectrum(load_astm("AM1.5d"))

        low_current_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=rev_diode)
        low_current_cell.set_input_spectrum(load_astm("AM1.5d") * 0.5)

        # A trick is used here to configure MJCell. The MJCell is not illuminated.
        # But each of the subcell is illuminated individually.
        tj_cell_1 = MJCell([copy.deepcopy(normal_cell) for i in range(4)] + [copy.deepcopy(low_current_cell)])

        tj_cell_2 = MJCell([copy.deepcopy(normal_cell) for i in range(5)])

        iv_funcs = [tj_cell_1.get_j_from_v, tj_cell_2.get_j_from_v]

        parallel_v, parallel_i = solve_parallel_connected_ivs(iv_funcs, vmin=-2, vmax=6, vnum=30)
        volt = np.linspace(-2, 6, num=30)
        curr_1 = tj_cell_1.get_j_from_v(volt)
        curr_2 = tj_cell_2.get_j_from_v(volt)

        plt.plot(volt, curr_1, '.-', label="string 1")
        plt.plot(volt, curr_2, '.-', label="string 2")
        plt.plot(parallel_v, parallel_i, '.-', label="parallel-connected string")
        plt.ylim([-600, 0])
        plt.legend()
        plt.show()
Пример #4
0
def no_reverse_diode():
    sq1_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=None)
    sq1_cell.set_input_spectrum(load_astm("AM1.5d") * 0.5)

    sq2_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=None)
    sq2_cell.set_input_spectrum(load_astm("AM1.5d"))

    sq3_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=None)
    sq3_cell.set_input_spectrum(load_astm("AM1.5d") * 1.1)

    iv_funcs = [
        sq1_cell.get_j_from_v, sq2_cell.get_j_from_v, sq3_cell.get_j_from_v
    ]

    volt = np.linspace(-1, 2, num=300)
    plt.plot(volt, sq1_cell.get_j_from_v(volt), '.-', label="cell 1")
    plt.plot(volt, sq2_cell.get_j_from_v(volt), '.-', label="cell 2")
    plt.plot(volt, sq3_cell.get_j_from_v(volt), '.-', label="cell 3")

    plt.ylim([-350, 0])
    plt.xlim([-1.5, 4])

    plt.xlabel("voltage (V)")
    plt.ylabel("current (A/m^2)")
    plt.legend()
    plt.savefig("./figs/no_rev_diode_iv.png", dpi=300)
    plt.savefig("./figs/no_rev_diode_iv.pdf")
    plt.show()

    plt.close()
    plt.figure()

    current_to_solve = sq1_cell.get_j_from_v(volt)
    current_to_solve = np.unique(current_to_solve)

    # plt.plot(volt, sq1_cell.get_j_from_v(volt),'.-',label="cell 1")
    sum_v = np.zeros_like(current_to_solve)
    for idx, iv_func in enumerate(iv_funcs[0:]):
        v, i = solve_v_from_j_by_bracket_root_finding(iv_func,
                                                      current_to_solve, -3, 5,
                                                      bisect)
        sum_v += v
        plt.plot(v, i, '.-', label="solved cell {}".format(idx + 1))

    # plot summed up the voltages
    plt.plot(sum_v, current_to_solve, '.-', label="connected cell")

    plt.ylim([-350, 0])
    plt.xlim([-1.5, 4])
    plt.xlabel("voltage (V)")
    plt.ylabel("current (A/m^2)")
    plt.legend()
    plt.savefig("./figs/no_rev_diode_iv_solved.png", dpi=300)
    plt.savefig("./figs/no_rev_diode_iv_solved.pdf")
    plt.show()
Пример #5
0
    def test_two_connected_mj_cells(self):
        """
        Test three series-connected triple-junction cells.
        We use MJCells.get_j_from_v() as the iv_func of the bracket-based root-finding solver.
        Warning: this is slow.

        :return:
        """

        sq1_cell = SQCell(eg=1.87, cell_T=300, plug_in_term=rev_diode)

        sq2_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=rev_diode)

        sq3_cell = SQCell(eg=1.0, cell_T=300, plug_in_term=rev_diode)

        tj_cell = MJCell([sq1_cell, sq2_cell, sq3_cell])
        tj_cell.set_input_spectrum(load_astm(("AM1.5d")))

        tj_cell_1 = copy.deepcopy(tj_cell)
        tj_cell_2 = copy.deepcopy(tj_cell)

        iv_funcs = [tj_cell_1.get_j_from_v, tj_cell_2.get_j_from_v]
        # solved_v,solved_i=solve_series_connected_ivs(iv_funcs, vmin=-2, vmax=3, vnum=10)
        volt_range = np.linspace(-1, 4, num=25)
        curr_range = tj_cell_1.get_j_from_v(volt_range)

        from scipy.optimize import brentq

        solved_v, solved_i = solve_v_from_j_by_bracket_root_finding(iv_funcs[0], curr_range, -5, 5, brentq)

        plt.plot(solved_v, solved_i, '.-')
        plt.ylim([-300, 0])
        plt.show()
Пример #6
0
    def test_dbcell2(self):

        qe_val = 0.8

        ill = load_astm("AM1.5g")

        gaas_qe = gen_step_qe(1.42, qe_val)

        gaas_db = DBCell(qe=gaas_qe, rad_eta=1, T=300)

        gaas_db.set_input_spectrum(ill)

        trans_sp = gaas_db.get_transmit_spectrum()

        # Compare the expected and transmitted spectrum

        x = np.linspace(1.5, 2, num=10)

        trans = trans_sp.get_interp_spectrum(x, to_x_unit='eV')

        orig = ill.get_interp_spectrum(x, to_x_unit='eV') * (1 - qe_val)

        cp = np.allclose(trans[1, :], orig[1, :])

        self.assertTrue(cp)
Пример #7
0
    def test_mj_j_from_v(self):
        """
        Test MJCell.get_j_from_v()

        :return:
        """
        sq1_cell = SQCell(eg=1.87, cell_T=300, plug_in_term=rev_diode)

        sq2_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=rev_diode)

        sq3_cell = SQCell(eg=1.0, cell_T=300, plug_in_term=rev_diode)

        tj_cell = MJCell([sq1_cell, sq2_cell, sq3_cell])
        tj_cell.set_input_spectrum(load_astm(("AM1.5d")))

        solved_mj_v, solved_mj_i = tj_cell.get_iv()

        volt = np.linspace(2.5, 5, num=300)
        solved_current = tj_cell.get_j_from_v(volt, max_iter=3)
        interped_i = np.interp(volt, solved_mj_v, solved_mj_i)

        print(solved_current - interped_i)

        plt.plot(volt, interped_i, '.-')
        plt.plot(solved_mj_v, solved_mj_i, '.-')
        plt.plot(volt, solved_current, '.-', label='get_j_from_v', alpha=0.3)

        plt.ylim([-200, 0])
        plt.legend()
        plt.show()
Пример #8
0
    def test_dbcell(self):

        gaas_qe = gen_step_qe(1.42, 1)

        gaas_db = DBCell(qe=gaas_qe, rad_eta=1, T=300)

        gaas_db.set_input_spectrum(load_astm("AM1.5g"))

        gaas_db_eta = gaas_db.get_eta()

        sq_gaas = SQCell(eg=1.42, cell_T=300)
        sq_gaas.set_input_spectrum(load_astm("AM1.5g"))

        sq_gaas_eta = sq_gaas.get_eta()

        self.assertTrue(np.isclose(gaas_db_eta, sq_gaas_eta, rtol=5e-3))
Пример #9
0
    def test_mj_cell_iv(self):
        """
        Test solving multi-junction cells, by breaking it down into series-connected subcells.

        :return:
        """
        sq1_cell = SQCell(eg=1.87, cell_T=300, plug_in_term=rev_breakdown_diode)

        sq2_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=rev_breakdown_diode)

        sq3_cell = SQCell(eg=1.0, cell_T=300, plug_in_term=rev_breakdown_diode)

        tj_cell = MJCell([sq1_cell, sq2_cell, sq3_cell])
        tj_cell.set_input_spectrum(load_astm(("AM1.5d")))

        solved_mj_v, solved_mj_i = tj_cell.get_iv()

        # plot the I-V of sq1,sq2 and sq3
        volt = np.linspace(-3, 3, num=300)
        plt.plot(volt, sq1_cell.get_j_from_v(volt), label="top cell")
        plt.plot(volt, sq2_cell.get_j_from_v(volt), label="middle cell")
        plt.plot(volt, sq3_cell.get_j_from_v(volt), label="bottom cell")

        plt.plot(solved_mj_v, solved_mj_i, '.-', label="MJ cell")
        plt.ylim([-200, 0])
        plt.xlim([-5, 6])

        plt.xlabel("voltage (V)")
        plt.ylabel("currnet (A/m^2)")
        plt.legend()
        plt.show()
Пример #10
0
    def test_parallel_connected_mj_cells(self):
        """
        Connected two triple-junction cells in parallel

        :return:
        """

        sq1_cell = SQCell(eg=1.87, cell_T=300, plug_in_term=rev_breakdown_diode)

        sq2_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=rev_breakdown_diode)

        sq3_cell = SQCell(eg=1.0, cell_T=300, plug_in_term=rev_breakdown_diode)

        tj_cell = MJCell([sq1_cell, sq2_cell, sq3_cell])
        tj_cell.set_input_spectrum(load_astm(("AM1.5d")))

        tj_cell_1 = copy.deepcopy(tj_cell)
        tj_cell_2 = copy.deepcopy(tj_cell)

        iv_funcs = [tj_cell_1.get_j_from_v, tj_cell_2.get_j_from_v]

        parallel_v, parallel_i = solve_parallel_connected_ivs(iv_funcs, vmin=-2, vmax=3.5, vnum=30)
        volt = np.linspace(-2, 3.5, num=30)
        curr = tj_cell_1.get_j_from_v(volt)

        plt.plot(volt, curr, '.-', label="single string")
        plt.plot(parallel_v, parallel_i, '.-', label="strings connected in parallel")
        plt.ylim([-600, 0])
        plt.show()
    def test_multi_junction_diode(self):
        hp1 = HighPSQCell(1.87, cell_T=300)
        hp1.set_input_spectrum(load_astm())

        hp2 = HighPSQCell(1.42, cell_T=300)
        hp2.set_input_spectrum(load_astm())

        hp3 = HighPSQCell(1.0, cell_T=300)
        hp3.set_input_spectrum(load_astm())

        d1 = DiodeSeriesConnect([hp1, hp2, hp3])

        test_v = 1.0
        j1 = d1.get_j_from_v(test_v)

        test_v = np.linspace(-2, 3.4, num=200)
        j1 = d1.get_j_from_v(test_v)

        plt.plot(test_v, j1)
        plt.show()
Пример #12
0
    def test_solving_five_cells(self):
        """
        Test five series-connected, non-uniform illuminated, Eg=1.42 solar cells

        :return:
        """

        sq1_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=rev_diode)
        sq1_cell.set_input_spectrum(load_astm("AM1.5d") * 0.5)

        sq2_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=rev_diode)
        sq2_cell.set_input_spectrum(load_astm("AM1.5d"))

        sq3_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=rev_diode)
        sq3_cell.set_input_spectrum(load_astm("AM1.5d"))

        sq4_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=rev_diode)
        sq4_cell.set_input_spectrum(load_astm("AM1.5d") * 1.5)

        sq5_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=rev_diode)
        sq5_cell.set_input_spectrum(load_astm("AM1.5d") * 0.75)

        iv_funcs = [sq1_cell.get_j_from_v, sq2_cell.get_j_from_v, sq3_cell.get_j_from_v, sq4_cell.get_j_from_v,
                    sq5_cell.get_j_from_v]

        iv_pair = solve_series_connected_ivs(iv_funcs=iv_funcs, vmin=-3, vmax=3, vnum=300)

        volt = np.linspace(-3, 3, num=300)
        plt.plot(volt, sq1_cell.get_j_from_v(volt))
        plt.plot(volt, sq2_cell.get_j_from_v(volt))
        plt.plot(volt, sq4_cell.get_j_from_v(volt))
        plt.plot(volt, sq5_cell.get_j_from_v(volt))

        plt.plot(iv_pair[0, :], iv_pair[1, :], '.-')
        plt.ylim([-500, 0])
        plt.xlim([-5, 6])

        plt.xlabel("voltage (V)")
        plt.ylabel("currnet (A/m^2)")
        plt.show()
 def setUp(self):
     self.dark_hpc = HighPSQCell(eg=1.42, cell_T=300)
     self.light_hpc = HighPSQCell(eg=1.42, cell_T=300)
     self.light_hpc.set_input_spectrum(load_astm())
Пример #14
0
 def setUp(self):
     self.input_ill = load_astm("AM1.5g")
Пример #15
0
def with_reverse_diode(plot_arrow=False):
    sq1_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=rev_diode)
    sq1_cell.set_input_spectrum(load_astm("AM1.5d") * 0.5)

    sq2_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=rev_diode)
    sq2_cell.set_input_spectrum(load_astm("AM1.5d"))

    sq3_cell = SQCell(eg=1.42, cell_T=300, plug_in_term=rev_diode)
    sq3_cell.set_input_spectrum(load_astm("AM1.5d") * 1.1)

    iv_funcs = [
        sq1_cell.get_j_from_v, sq2_cell.get_j_from_v, sq3_cell.get_j_from_v
    ]

    volt = np.linspace(-3, 2, num=300)
    arrow_dx = volt + 1.0
    arrow_dy = np.zeros_like(volt)
    plt.plot(volt, sq1_cell.get_j_from_v(volt), '.-', label="cell 1")
    prev_current = None

    if plot_arrow:
        for v in volt:
            current = sq1_cell.get_j_from_v(v)
            if (prev_current is None) or (np.isclose(
                    current, prev_current, rtol=5e-2) == False):
                plt.arrow(v,
                          sq1_cell.get_j_from_v(v),
                          2.0 - v,
                          0,
                          color='C0',
                          linestyle='--')
            prev_current = current

    plt.plot(volt, sq2_cell.get_j_from_v(volt), '.-', label="cell 2")

    prev_current = None
    if plot_arrow:
        for v in volt:
            current = sq2_cell.get_j_from_v(v)
            if (prev_current is None) or (np.isclose(
                    current, prev_current, rtol=5e-2) == False):
                plt.arrow(v,
                          sq2_cell.get_j_from_v(v),
                          2.0 - v,
                          0,
                          color='C1',
                          linestyle='--')
            prev_current = v

    plt.plot(volt, sq3_cell.get_j_from_v(volt), '.-', label="cell 3")

    prev_current = None
    if plot_arrow:
        for v in volt:
            current = sq3_cell.get_j_from_v(v)
            if (prev_current is None) or (np.isclose(
                    current, prev_current, rtol=5e-2) == False):
                plt.arrow(v,
                          sq3_cell.get_j_from_v(v),
                          2.0 - v,
                          0,
                          color='C2',
                          linestyle='--')
            prev_current = v

    plt.ylim([-350, 0])
    plt.xlim([-1.5, 4])

    plt.xlabel("voltage (V)")
    plt.ylabel("current (A/m^2)")
    plt.legend()
    plt.savefig("./figs/with_rev_diode_iv.png", dpi=600)
    plt.savefig("./figs/with_rev_diode_iv.pdf")
    plt.show()

    plt.close()
    plt.figure()

    solved_iv, subcell_ivs = solve_series_connected_ivs(iv_funcs,
                                                        -2,
                                                        3,
                                                        100,
                                                        return_subcell_iv=True,
                                                        add_epsilon=0.0)

    # plot sub cell I-Vs
    for subcell_id in range(3):
        plt.plot(subcell_ivs[subcell_id, 0, :],
                 subcell_ivs[subcell_id, 1, :],
                 '.-',
                 label="cell {}".format(subcell_id + 1))

    # plot summed up the voltages
    plt.plot(solved_iv[0], solved_iv[1], '.-', label="connected cell")

    plt.ylim([-350, 0])
    plt.xlim([-3, 4])
    plt.xlabel("voltage (V)")
    plt.ylabel("current (A/m^2)")
    plt.legend()
    plt.savefig("./figs/with_rev_diode_iv_solved.png", dpi=600)
    plt.savefig("./figs/with_rev_diode_iv_solved.pdf")

    plt.show()
Пример #16
0
from pypvcell.solarcell import SQCell
import numpy as np
import matplotlib.pyplot as plt
import scipy.constants as sc
from pypvcell.illumination import load_astm


def rev_diode(voltage):
    rev_j01 = 4.46e-19
    rev_bd_v = 20
    return -rev_j01 * np.exp(sc.e * (-voltage - rev_bd_v) / (sc.k * 300) - 1)


sq1_cell = SQCell(eg=1.3, cell_T=300, plug_in_term=rev_diode)
sq1_cell.set_input_spectrum(load_astm("AM1.5d"))

test_v = np.linspace(-21, 1.5, num=100)

test_j = sq1_cell.get_j_from_v(test_v)

print(test_j)

# model reverse breakdown

print(sq1_cell.j01)

plt.plot(test_v, test_j)

plt.show()
plt.close()
Пример #17
0
 def test_load_astm_fail(self):
     spec = "AM1.5j"
     with self.assertRaises(ValueError):
         ill = load_astm(spec)
Пример #18
0
 def test_something(self):
     spec = "AM1.5g"
     ill = load_astm(spec)
     tp = ill.rsum()
     print("total power of {0}:{1}".format(spec, tp))
     self.assertAlmostEqual(tp, 1000.370, places=2)