Source code for pvdeg.collection

"""Collection of functions related to calculating current collection in solar cells
"""

import numpy as np
from scipy.integrate import simpson
from scipy.interpolate import interp1d
from scipy.constants import elementary_charge
import photovoltaic as pv


[docs] def collection_probability(x, thickness, s, l, d): """ Returns the collection probability (unit 0 to 1) at a distance x (cm) from the junction. See [1]_. Parameters ---------- x : array-like array of x positions from a junction to a surface (typically [cm]). thickness : numeric Layer thickness [cm]. s : numeric Surface recombination velocity [cm/s]. l : numeric Minority carrier diffusion length [cm]. d : numeric Minority carrier diffusivity [cm^2/Vs]. Returns ------- cp : array-like Collection probability along x. References ---------- .. [1] https://www.pveducation.org/pvcdrom/solar-cell-operation/collection-probability """ cosh_xl = np.cosh(x / l) cosh_wl = np.cosh(thickness / l) sinh_xl = np.sinh(x / l) sinh_wl = np.sinh(thickness / l) num = s * l / d * cosh_wl + sinh_wl den = s * l / d * sinh_wl + cosh_wl cp = cosh_xl - (num / den) * sinh_xl return cp
[docs] def calculate_jsc_from_tau_cp( tau, wafer_thickness, d_base, s_rear, generation, depth, w_emitter=0.36, l_emitter=15, d_emitter=5, s_emitter=1e4, xp=0.00000024, ): """ Returns cell Jsc given lifetime and cell parameters Jsc is calculated via integrating collection probability and optical generation profiles through the wafer depth. Includes contribution of the emitter, depletion region (assumes CP = 1 in the depletion region), and base. Parameters ---------- tau : numeric Carrier lifetime [us]. wafer_thickness : numeric Wafer thickness [um]. d_base : numeric Minority carrier diffusivity [cm^2/Vs]. s_rear : numeric Rear surface recombination velocity [cm/s]. generation : array-like array of generation current G(z), e.g. from PVlighthouse OPAL2 [cm^3/s] [1]_. depth : array-like array of wafer depth 0-z [um]. w_emitter : numeric, default 0.36 Emitter thickness [um]. l_emitter : numeric, default 15 Minority carrier diffusion length of the emitter [um]. d_emitter : numeric, default 5 Minority carrier diffusivity in the emitter [cm^2/s]. s_emitter : numeric, default 1e4 Front surface recombination velocity [cm/s]. xp : numeric, default 0.00000024 width of the depletion region [m]. Treated as fixed width, as it is very small compared to the bulk, so injection-dependent variations will have very small effects. Returns ------- jsc : numeric Short circuit current of the solar cell [mA/cm^2]. Notes ----- Default emitter parameters w, l, d, and s are supplied, but users may wish to experiment to find the most suitable parameters to model different cell types. Default values are adapted from [2]_ and [3]_. Pros of this approach can account for e.g. lighttrapping via the generation profile Cons of this approach requires a generation profile Future work: include default generation and depth profile. References ---------- .. [1] K. R. McIntosh and S. C. Baker-Finch, “OPAL 2: Rapid optical simulation of silicon solar cells,” in 2012 38th IEEE Photovoltaic Specialists Conference, IEEE, 2012, pp. 000265–000271. doi: 10.1109/PVSC.2012.6317616. .. [2] A. Fell et al., “Input Parameters for the Simulation of Silicon Solar Cells in 2014,” IEEE Journal of Photovoltaics, vol. 5, no. 4, pp. 1250–1263, Jul. 2015, doi: 10.1109/JPHOTOV.2015.2430016. .. [3] W. J. Yang, Z. Q. Ma, X. Tang, C. B. Feng, W. G. Zhao, and P. P. Shi, “Internal quantum efficiency for solar cells,” Solar Energy, vol. 82, no. 2, pp. 106–110, Feb. 2008, doi: 10.1016/j.solener.2007.07.010. """ q = elementary_charge # Unit conversions: w_depletion = xp * 100 # depletion region width, m to cm w_emitter = w_emitter * 1e-4 # um to cm l_emitter = l_emitter * 1e-4 w_base = wafer_thickness * 1e-4 - w_emitter # width of the base in cm tau = tau * 1e-6 # us to s s_base = s_rear # cm/s depth = depth * 1e-4 # um to cm # 1. calc diffusion length l_base = np.sqrt(tau * d_base) # diffusion length in cm # 2. set up depth profile and cell regions index_emitter = np.searchsorted(depth, w_emitter) emitter_depth = depth[0:index_emitter] emitter_depth = np.flip((-emitter_depth + np.max(emitter_depth)).to_numpy()) index_depletion = np.searchsorted(depth, w_emitter + w_depletion) depletion_depth = depth[index_emitter:index_depletion] base_depth = depth[index_depletion:] # 3. calc c.p. for emitter, depletion region, and base cp_emitter = collection_probability( emitter_depth, thickness=w_emitter, s=s_emitter, l=l_emitter, d=d_emitter ) cp_emitter = np.flip(cp_emitter) emitter_depth = np.flip((-emitter_depth + np.max(emitter_depth))) cp_depletion = np.ones(len(depletion_depth)) cp_base = collection_probability(base_depth, w_base, s_base, l_base, d_base) depth_array = np.concatenate( np.array([emitter_depth, depletion_depth, base_depth], dtype=object), axis=0 ) collection_array = np.concatenate( np.array([cp_emitter, cp_depletion, cp_base], dtype=object), axis=0 ) # 4. Reinterpolate to match the generation depth profile f = interp1d(depth_array, collection_array, kind="cubic") collection_array_interp = f(depth) # 5. integrate jsc = simpson(collection_array_interp * generation, depth) * q return jsc * 1000
[docs] def calculate_jsc_from_tau_iqe( tau, wafer_thickness, d_base, s_rear, spectrum, absorption, wavelengths, w_emitter=0.36, l_emitter=15, d_emitter=5, s_emitter=1e4, xp=0.00000024, ): """ Returns cell Jsc given lifetime and cell parameters Calculates Jsc via calculating cell internal quantum efficiency (IQE) and absorption for Si Parameters ---------- tau : numeric Carrier lifetime [us]. wafer_thickness : numeric Wafer thickness [um]. d_base : numeric Minority carrier diffusivity [cm^2/Vs]. s_rear : numeric Rear surface recombination velocity [cm/s]. spectrum : array-like photon flux density solar spectrum. absorption : array-like absorption coefficient of Si, e.g. loaded from 'photovoltaic' library [1]_. wavelengths : array-like wavelength series (nm) for absorption coefficient and solar spectrum. w_emitter : numeric, default 0.36 Emitter thickness [um]. l_emitter : numeric, default 0.5 Diffusion length of the emitter [um]. d_emitter : numeric, default 4 Minority carrier diffusivity in the emitter [cm^2/s]. s_emitter : numeric, default 4.86e5 Front surface recombination velocity [cm/s]. xp : numeric, default 0.00000024 width of the depletion region [m]. Treated as fixed width, as it is very small compared to the bulk, so injection-dependent variations will have very small effects. Returns ------- jsc : numeric Short circuit current of the solar cell [mA/cm^2] Notes ----- Default emitter parameters w, l, d, and s are supplied, but users may wish to experiment to find the most suitable parameters to model different cell types. Default values are adapted from [2]_ and [3]_. Pros of this approach: requires only fundamental inputs: Si absorption and spectrum Cons: does not account for any anti-reflection or light trapping To do: accept user inputs for spectrum and absorption, otherwise use photovoltaic library References ---------- .. [1] “photovoltaic.” https://github.com/pvedu/photovoltaic .. [2] A. Fell et al., “Input Parameters for the Simulation of Silicon Solar Cells in 2014,” IEEE Journal of Photovoltaics, vol. 5, no. 4, pp. 1250–1263, Jul. 2015, doi: 10.1109/JPHOTOV.2015.2430016. .. [3] W. J. Yang, Z. Q. Ma, X. Tang, C. B. Feng, W. G. Zhao, and P. P. Shi, “Internal quantum efficiency for solar cells,” Solar Energy, vol. 82, no. 2, pp. 106–110, Feb. 2008, doi: 10.1016/j.solener.2007.07.010. """ # Unit conversions: w_depletion = xp * 100 # depletion region width, m to cm w_emitter = w_emitter * 1e-4 l_emitter = l_emitter * 1e-4 w_base = wafer_thickness * 1e-4 - w_emitter # width of the base in cm tau = tau * 1e-6 # us to s s_base = s_rear # cm/s # 1. calculate diffusion length l_base = np.sqrt(tau * d_base) # diffusion length in cm # 2. calculate iqe _, _, _, qet = pv.cell.iqe( absorption, w_depletion, s_emitter, l_emitter, d_emitter, w_emitter, s_base, w_base, l_base, d_base, ) # 3. integrate iqe with spectrum jsc = simpson(qet * spectrum, wavelengths) / 10 return jsc
[docs] def generation_current(generation, depth): """ Returns cell generation current given generation profile Parameters ---------- generation : array-like array of generation current G(z), e.g. from PVlighthouse OPAL2 [cm^3/s] [1]_. depth : array-like array of wafer depth 0-z [um]. Returns ------- j_gen : numeric generation current [mA/cm^2] """ q = elementary_charge j_gen = simpson(generation, depth) * q / 10 return j_gen