{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from solcore import material\n", "from solcore.structure import Layer, Junction, TunnelJunction\n", "from solcore.solar_cell import SolarCell\n", "from solcore.solar_cell_solver import solar_cell_solver\n", "from solcore.light_source import LightSource\n", "import solcore.poisson_drift_diffusion as PDD" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "T = 298\n", "wl = np.linspace(350, 1050, 301) * 1e-9" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, we create the materials of the QW" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "QWmat = material(\"InGaAs\")(T=T, In=0.2, strained=True)\n", "Bmat = material(\"GaAsP\")(T=T, P=0.1, strained=True)\n", "i_GaAs = material(\"GaAs\")(T=T)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The QW is 7 nm wide, with GaAs interlayers 2 nm thick at each side and GaAsP barriers
\n", "10 nm thick. The final device will have 30 of these QWs." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "QW = PDD.QWunit(\n", " [\n", " Layer(width=10e-9, material=Bmat, role=\"barrier\"),\n", " Layer(width=2e-9, material=i_GaAs, role=\"well\"),\n", " Layer(width=7e-9, material=QWmat, role=\"well\"),\n", " Layer(width=2e-9, material=i_GaAs, role=\"well\"),\n", " Layer(width=10e-9, material=Bmat, role=\"barrier\"),\n", " ],\n", " T=T,\n", " repeat=30,\n", " substrate=i_GaAs,\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We solve the quantum properties of the QW, leaving the default values of all
\n", "parameters" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "QW_list = QW.GetEffectiveQW(wavelengths=wl)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Materials for the BOTTOM junction" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "window_bottom = material(\"GaInP\")(T=T, Nd=5e24, In=0.49)\n", "n_GaAs = material(\"GaAs\")(T=T, Nd=1e24)\n", "p_GaAs = material(\"GaAs\")(T=T, Na=8e22)\n", "bsf_bottom = material(\"GaInP\")(T=T, Na=5e24, In=0.49)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you want to test the code without QWs, to make ti a bit faster, comment the line
\n", "with QW_list" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "GaAs_junction = Junction(\n", " [\n", " Layer(width=10e-9, material=window_bottom, role=\"Window\"),\n", " Layer(width=150e-9, material=n_GaAs, role=\"Emitter\"),\n", " ]\n", " # Comment the following line to remove the QWs\n", " + QW_list\n", " + [\n", " Layer(width=2000e-9, material=p_GaAs, role=\"Base\"),\n", " Layer(width=200e-9, material=bsf_bottom, role=\"BSF\"),\n", " ],\n", " sn=1e6,\n", " sp=1e6,\n", " T=T,\n", " kind=\"PDD\",\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Materials for the TOP junction" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "window_top = material(\"AlInP\")(\n", " T=T, Nd=5e23, Al=0.53, electron_mobility=0.01, hole_mobility=7e-4\n", ")\n", "n_GaInP = material(\"GaInP\")(T=T, Nd=5e23, In=0.49)\n", "p_GaInP = material(\"GaInP\")(T=T, Na=8e22, In=0.49)\n", "bsf_top = material(\"AlInP\")(\n", " T=T, Na=5e23, Al=0.53, electron_mobility=0.01, hole_mobility=7e-4\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We create the Top junction, leaving outside the window and bsf layers. They work
\n", "well in the dark, but cause convergence issues under illumination." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "GaInP_junction = Junction(\n", " [\n", " Layer(width=120e-9, material=n_GaInP, role=\"Emitter\"),\n", " Layer(width=800e-9, material=p_GaInP, role=\"Base\"),\n", " ],\n", " sn=1e3,\n", " sp=1e3,\n", " T=T,\n", " kind=\"PDD\",\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We create the tunnel junction" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "tunnel = TunnelJunction(\n", " [Layer(width=40e-9, material=n_GaInP, role=\"TJ\")],\n", " v_peak=0.2,\n", " j_peak=7.5e4,\n", " v_valley=1,\n", " j_valley=4e4,\n", " prefactor=5,\n", " j01=1e-23,\n", " kind=\"parametric\",\n", " pn=True,\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And the materials needed for the anti reflecting coating" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "MgF2 = material(\"MgF2\")()\n", "ZnS = material(\"ZnScub\")()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, we put everithing together to make a solar cell" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "my_solar_cell = SolarCell(\n", " [\n", " Layer(width=110e-9, material=MgF2, role=\"ARC1\"),\n", " Layer(width=60e-9, material=ZnS, role=\"ARC2\"),\n", " Layer(width=30e-9, material=window_top, role=\"window\"),\n", " GaInP_junction,\n", " Layer(width=100e-9, material=bsf_top, role=\"BSF\"),\n", " tunnel,\n", " GaAs_junction,\n", " ],\n", " T=T,\n", " substrate=n_GaAs,\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "light_source = LightSource(\n", " source_type=\"standard\",\n", " version=\"AM1.5g\",\n", " x=wl,\n", " output_units=\"photon_flux_per_m\",\n", " concentration=1,\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The definitions are all done, so we just start solving the properties,
\n", "starting with the QE. We calculate the QE curve under illumination" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "solar_cell_solver(\n", " my_solar_cell,\n", " \"qe\",\n", " user_options={\n", " \"light_source\": light_source,\n", " \"wavelength\": wl,\n", " \"optics_method\": \"TMM\",\n", " },\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And now, the IV curves under various concentration levels.
\n", "NOTE: Due to the presence of QWs and the fact we calculate things a 19 different
\n", "concentrations, this might take a while (~4 hours).
\n", "Remove the QWs as indicated above to test the code much faster." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "num_con = 19\n", "con = np.logspace(0, 3, num_con)\n", "vint = np.linspace(-3.5, 4, 600)\n", "V = np.linspace(-3.5, 0, 300)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "allI = []\n", "isc = []\n", "voc = []\n", "FF = []\n", "pmpp = []" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig3, axIV = plt.subplots(1, 1, figsize=(6, 4))\n", "for c in con:\n", " light_source.options[\"concentration\"] = c\n", " solar_cell_solver(\n", " my_solar_cell,\n", " \"iv\",\n", " user_options={\n", " \"light_source\": light_source,\n", " \"wavelength\": wl,\n", " \"optics_method\": None,\n", " \"light_iv\": True,\n", " \"mpp\": True,\n", " \"voltages\": V,\n", " \"internal_voltages\": vint,\n", " },\n", " )\n", " isc.append(my_solar_cell.iv[\"Isc\"])\n", " voc.append(my_solar_cell.iv[\"Voc\"])\n", " FF.append(my_solar_cell.iv[\"FF\"])\n", " pmpp.append(my_solar_cell.iv[\"Pmpp\"])\n", " allI.append(my_solar_cell.iv[\"IV\"][1])\n", "\n", " # And now, everything is plotting...\n", " axIV.plot(-V, my_solar_cell.iv[\"IV\"][1] / isc[-1], label=int(c))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "axIV.legend(loc=\"lower left\", frameon=False)\n", "axIV.set_ylim(0, 1.1)\n", "axIV.set_xlim(0, 3.5)\n", "axIV.set_xlabel(\"Voltage (V)\")\n", "axIV.set_ylabel(\"Normalized current (-)\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.tight_layout()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig2, axes = plt.subplots(2, 2, figsize=(11.25, 8))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "axes[0, 0].semilogx(con, np.array(pmpp) / con / 10, \"r-o\")\n", "axes[0, 0].set_xlabel(\"Concentration (suns)\")\n", "axes[0, 0].set_ylabel(\"Efficiency (%)\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "axes[0, 1].loglog(con, abs(np.array(isc)), \"b-o\")\n", "axes[0, 1].set_xlabel(\"Concentration (suns)\")\n", "axes[0, 1].set_ylabel(\"I$_{SC}$ (Am$^{-2}$)\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "axes[1, 0].semilogx(con, abs(np.array(voc)), \"g-o\")\n", "axes[1, 0].set_xlabel(\"Concentration (suns)\")\n", "axes[1, 0].set_ylabel(\"V$_{OC}$ (V)\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "axes[1, 1].semilogx(con, abs(np.array(FF)) * 100, \"k-o\")\n", "axes[1, 1].set_xlabel(\"Concentration (suns)\")\n", "axes[1, 1].set_ylabel(\"Fill Factor (%)\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.tight_layout()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can plot the electron and hole densities in equilibrium and at short circuit" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(11.25, 4))\n", "for j in my_solar_cell.junction_indices:\n", " zz = (\n", " my_solar_cell[j].short_circuit_data.Bandstructure[\"x\"] + my_solar_cell[j].offset\n", " )\n", " n = my_solar_cell[j].short_circuit_data.Bandstructure[\"n\"]\n", " p = my_solar_cell[j].short_circuit_data.Bandstructure[\"p\"]\n", " ax1.semilogy(zz * 1e9, n, \"b\")\n", " ax1.semilogy(zz * 1e9, p, \"r\")\n", " zz = my_solar_cell[j].equilibrium_data.Bandstructure[\"x\"] + my_solar_cell[j].offset\n", " n = my_solar_cell[j].equilibrium_data.Bandstructure[\"n\"]\n", " p = my_solar_cell[j].equilibrium_data.Bandstructure[\"p\"]\n", " ax1.semilogy(zz * 1e9, n, \"b--\")\n", " ax1.semilogy(zz * 1e9, p, \"r--\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ax1.set_xlabel(\"Position (nm)\")\n", "ax1.set_ylabel(\"Carrier density (m$^{-3}$)\")\n", "plt.tight_layout()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And we plot the QE" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "labels = [\"EQE GaInP\", \"EQE GaAs\"]\n", "colours = [\"b\", \"r\"]\n", "for i, j in enumerate(my_solar_cell.junction_indices):\n", " ax2.plot(wl * 1e9, my_solar_cell[j].eqe(wl), colours[i], label=labels[i])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ax2.plot(wl * 1e9, my_solar_cell.absorbed, \"k\", label=\"Total Absorbed\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ax2.legend(loc=\"upper right\", frameon=False)\n", "ax2.set_xlabel(\"Wavelength (nm)\")\n", "ax2.set_ylabel(\"EQE\")\n", "ax2.set_ylim(0, 1.1)\n", "ax2.set_xlim(350, 1150)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.tight_layout()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.show()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.4" } }, "nbformat": 4, "nbformat_minor": 2 }