{
"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.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
}