pvcircuit contains objects that are building blocks for PV modeling and interactive data fitting.
Based on publications:
2 terminal multijunction model:
3 terminal tandem model:
Luminescent coupling correction of EQE:
Energy yield:
- install GitHub Desktop
- on this https://github.com/NREL/PVcircuit page click the green "Code" button and "Open with GitHub Desktop"
- cd to the PVcircuit directory in terminal and type "pip install -e ."
- pandas
- numpy
- matplotlib
- scipy
- ipywidgets
- ipympl
- parse
- num2words
- tandems
for fast energy yield calculations:
git clone https://github.com/Ripalda/Tandems ~/Documents/GitHub/Tandems
cd ~/Documents/GitHub/Tandems
pip install -e .
A single Junction that can be combined together to form tandem and multijunction solar cells.
The Junction is modeled by an arbitrary number of parallel diodes such as n=1, n=2, n=2/3, or any other ideality factor. The temperature dependance of each diode saturation current J0n is determined relative to the Jdb(Eg,T).
Name of this junction string
Junction bandgap (eV)
Junction temperature (°C)
Junction shunt conductance (S/cm2)
Junction series resistance (Ohm cm2)
Illuminated area (cm2)
Total area including any dark area (cm2) always greater than or equal to .lightarea
External photocurrent (A/cm2)
Luminescent coupling photocurrent (A/cm2)
Electro luminescent coupling factor (unitless) Amount of light collected as current in an adjectent junction relative to Jdb
Photo luminescent coupling factor (unitless)
Direction of pn diode -1 n-on-p 0 simple resistor 1 p-on-n
Ideality factor numpy.array
Ratio of saturation current densities relative to Jdb numpy.array
J0ratio = J0 / (Jdb)^(1/n)
User interface created by .controls() Consists of plot, widget controls, and other outputs
Hidden output of for debugging
Temperature (K) from TC
Thermal voltage = kT/q from TK
Detailed balance current (A/cm2). If J0ratio for n=1 only this is Shockley-Quiesser limit
Total photocurrent = Jext+JLC
Reverse saturation currents (A/cm2) corresponding to each n[] and J0ratio[] numpy.array
Create a copy of a Junction
Controlled change of Junction attributes
Create a user interface Junction.ui which consists of widget controls that are mainly used to build up Multi2T.ui and Tandem3T.ui
Update Junction attributes into Junction.ui controls if they exist
initialize self.J0ratio from J0ref
returns np.ndarray [J0(n0), J0(n1), etc]
Light emitted from junction by reciprocity, quantified as current density (A/cm2)
boolean whether the junction is a junction (False) or resistor (True)
Calculate total recombination current density from multiple parallel diodes: n[], J0[] given voltage across diode without series resistance.
returns shunt + reverse-bias breakdown current
RBB_dict={'method':None}
RBB_dict={'method':'JFG', mrb'':10., 'J0rb':1., 'Vrb':0.}
RBB_dict={'method':'bishop','mrb'':3.28, 'avalanche':1, 'Vrb':-5.5}
RBB_dict={'method':'pvmismatch','ARBD':arbd,'BRBD':brbd,'VRBD':vrb,'NRBD':nrbd}
Circuit equation to be zeroed to solve for Vi for voltage across parallel diodes with shunt and reverse breakdown.
Calculate voltage across diode without series resistance as a function current density through the diode.
Circuit equation to be zeroed (returns voltage difference) to solve for Vmid. Single junction circuit with series resistance and parallel diodes. internal use only
Find intermediate voltage in a single junction diode with series resistance given Vtot including series resistance
Vtot = Vparallel + Rser * Jparallel
Two terminal multijunction device composed of any number of series connected Junctions. The sum of all Rser is an attribute of the Multi2T object and the Rser attributes of each sub Junction are ignored
Name of this junction string
Total series resistance of Multi2T. (Junction.Rser are ignored)
Number of junctions contained in Multi2T
List of Junction objects series-connected within Multi2T object
List of intermediate voltages between series-connected junctions
User interface created by Multi2T.controls() which consists of plot, widget controls, and other outputs
Hidden output of for debugging
Maximum of the contained Junction.TCs
Maximum of the contained Junction.lightareas
Maximum of the contained Junction.totalareas
Create a copy of this Multi2T object
Create a Multi2T object from a Tandem3T object
Create a Multi2T object from a Junction object
Controlled change of Multi2T and its Junction's attributes
Create a list of the scalar attributes or properties of the Junctions within a Multi2T object
Create a user interface Multi2T.ui which consists of plot, widget controls, and other outputs
Update Multi2T and its Junction's attributes into Multi2T.ui controls if they exist
Calculates the total Multi2T voltage as a function of the series-connected current
Also sets Multi2T.Vmid[]
Inputs scalar and outputs scalar.
Can be vectorized by
V2Tvect = np.vectorize(self.V2T)
Calculates the series-connected current as a function of total current Multi2T voltage.
Also sets Multi2T.Vmid[]
Inputs scalar and outputs scalar.
Can be vectorized by
I2Tvect = np.vectorize(self.I2T)
maximum reverse-bias current (A) without Gsh or breakdown
Open-circuit voltate (V) of Muli2T object
Short-circuit current (A) of Multi2T object
Fast method to calculate the maximum power point of Multi2T object. Outputs dictionary:
{"Voc":Voc, "Isc":Isc, "Vmp":Vmp, "Imp":Imp, "Pmp":Pmp, "FF":FF}
Calculate a dark IV curve outputs: (Idark, Vdark, Vdarkmid)
Calculate a light IV curve outputs: (Vlight, Ilight, Plight, MPP)
Multi2T.plot(title='', pplot=False, dark=None, pnts=21, Vmin= -0.5, lolog = -8, hilog = 7, pdec = 5)
Create a light or dark plot modeled from Multi2T parameters. Outputs: (mpl.Figure, mpl.Axes)
Three terminal (3T) tandem composed of two Junctions. Four terminal (4T) tandems can be modeled as 3T tandems with no resistive coupling (Rz=0) but still require luminescent coupling. The 4T shunt (or breakdown) between the subcells is not treated but could become important for large voltage differences.
Name of this junction string
Common series resistance of Tandem3T z-terminal
Top Junction object of Tandem3T object
Bottom Junction object of Tandem3T object
User interface created by Tandem3T.controls() which consists of plot, widget controls, and other outputs
Hidden output of for debugging
Maximum of the contained Junction.TCs
Maximum of the contained Junction.lightareas
Maximum of the contained Junction.totalareas
Create a copy of this Tandem3T object
Controlled change of Tandem3T and its Junction's attributes
Create a user interface Tandem3T.ui which consists of plot, widget controls, and other outputs
Update Tandem3T and its Junction's attributes into Tandem3T.ui controls if they exist
Calcuate iv3T.(Vzt,Vrz,Vtr) from iv3T.(Iro,Izo,Ito)
input/output IV3T object
Calcuate (Jro,Jzo,Jto) mapped -> iv3T.(Iro,Izo,Ito) from ABSOLUTE (Vz,Vr,Vt) mapped <- iv3T.(Vzt,Vrz,Vtr)
input/output IV3T object
calcuate (Jro,Jzo,Jto) mapped -> iv3T.(Iro,Izo,Ito) from RELATIVE iv3T.(Vzt,Vrz,Vtr) ignoring Vtr
input/output IV3T object
Return dI = Iro + Izo + Ito function solved for dI(Vz)=0 in I3rel
input Vzt, Vrz, IV3T object
Triple Voc of 3T tandem returns IV3T object.
returns IV3T object with one point
(Vzt, Vrz, Vtr) of (Iro = 0, Izo = 0, Ito = 0)
Triple Isc of 3T tandem returns IV3T object.
returns IV3T object with one point
(Iro, Izo, Ito ) of (Vzt = 0, Vrz = 0, Vtr = 0)
Iteratively find unconstrained MPP from lines as experimentally done. Varying I is faster than varying V but initial guess is not as good.
returns IV3T object with one point
'less' must be > 1.0. If FF is really bad, may need larger 'less'
Use 'bplot' for debugging information
Create voltage matched (VM) constrained line for tandem3T. Focus iteratively on the MPP of the constrained line.
'bot' bottom subcells in parallel with 'top' top subcells
returns two IV3T objects - the constrained line and MPP
Create current matched (CM) constrained line for tandem3T. Focus iteratively on the MPP of the constrained line.
returns two IV3T objects - the constrained line and MPP
Solve for mixed (V=0, I=0) zero power points using separate diodes for quick solutions
returns IV3T object with one point
Solve for mixed (V=0, I=0) zero power points does not work well
Compile all the special zero power points into a labeled IV3T object
Calculate and plot Tandem3T device
Structure to contain all the information about the operational state of a 3T tandem.
Device parameters calculated for a 'Tandem3T' object.
(Iro, Izo, Ito) <-> (Vzt, Vrz, Vtr)
Device paramters converted to load parameters for given measurement configuration (CZ, CR, CT).
(Iro, Izo, Ito) <-> (IA, IB)
(Vzt, Vrz, Vtr) <-> (VA, VB)
Hexagonal representation of 3 device parameters in 2 dimensions.
(Iro, Izo, Ito) <-> (Ixhex, Iyhex)
(Vzt, Vrz, Vtr) <-> (Vxhex, Vyhex)
string Name of this IV3T
string Measurement type of IV3T object 'CZ', 'CR', 'CT', 'CF', 'CRo', 'CTo', 'CZo', or 'CFo'
Shape of numpy.array that contains array points of IV3T object. tuple either 1D ie. (npts,) or 2D (xpnts, ypnts)
float cell area used to calculate current density or power density from current or power
string Name of the arraykey that is systematically varied.
string Name of the orthoganal arraykey that is systematically varied by IV3T.box() or constrained by IV3T.line()
1D ndarray of xkey values of box or line
1D ndarray of ykey values of box or line
List of labels of each point within IV3T using a string (optional but used by special points)
1D or 2D ndarray of current (A) values for each Tandem3T operating point.
[Iro,Izo,Ito] are device currents.
[IA, IB] are load currents relative to meastype
1D or 2D ndarray of device voltage (V) values for each Tandem3T operating point
[Vzt,Vrz,Vtr] are device voltages.
[VA, VB] are load voltage relative to meastype
1D or 2D ndarray of device voltage (V) or current (A) values mapped onto a 2D isometric hexagonal representation.
1D or 2D ndarray of total Tandem3T powers
Create a separate complete copy of a IV3T
Create a 1D ndarray on xkey with evenly spaced values in IV3T..x
ykey is constrained to xkey with eval expression using 'x'
Create a 2D ndarray for xkey and ykey with shape (xn, yn) with evenly spaced values. IV3T.x are values in one dimention. IV3T.y are values in orthogonal dimention
Add hexagonal grid lines to mpl.Axes. Range determined from self box IV3T object
Make indexed point in each keyarray an nan where index is a tuple i = (i, ) or (i,j)
Find the MPP from within points of IV3T and return a new IV3T object with one point.
Return a range of sizes of the array attributes in klist. Returns tuple (nmin,nmax)
Resize IV3T arrays and clears the values
Appends one IV3T object onto another
Initialize output arrays to nan if input arrays are consistent
Apply or check Kirchoff's law on [Iro,Izo,Ito] or [Vzt,Vrz,Vtr]
Input a list of 2 or 3 of the device input keys:
2 -> calculate the third device value from other two knowns
3 -> check the validity of 3 device parameters
Calculate Ptot after converting using oper = 'dev2load' or 'load2dev'
Return descriptive axis label for load variables. Add an extra character to swap the loads: 'CRo','CTo','CZo', 'CFo'
Calculate some array values from other array values. Can optionally set the meastype here.
VorI: 'V' or 'I'
oper: 'load2dev', 'dev2load', 'dev2hex', 'hex2dev' (not developed yet)
meastype: 'CR','CT','CZ','CF' or swap the loads: 'CRo','CTo','CZo', 'CFo'
import csv file as data table into iv3T object
two 2D arrays with x and y index on top and left
load variables:
VA(IA,IB) & VB(IA,IB) .......... VorI='I'
or
IA(VA,VB) & IB(VA,VB) .......... VorI='V'
Iscale converts current mA -> A or mA/cm2-> A
IV3T.plot(xkey = None, ykey = None, zkey = None, inplot = None, cmap='terrain', ccont = 'black', bar = True)
Plot 2D IV3T object zkey(xkey,ykey) as image if evenly spaced or randomly spaced with contours
Plot IV3T points or lines onto existing axes
Object to contain all EQE information
string Name of this EQE object
numpy.array 2D(lambda)(junction) raw input rawEQE (not LC corrected)
numpy.array wavelengths [nm] for rawEQE data
int number of junctions
str names of junctions used in plot legend
int number of wavelengths in rawEQE data
numpy.array luminescent coupling corrected EQE same size as rawEQE
numpy.array LC factor for next three junctions
Calculate LC corrected EQE using procedure from Steiner et al., IEEE PV, v3, p879 (2013)
Creates self.corrEQE
Calculate Jscs and Egs from self.corrEQE
Integrate junction currents = integrate (spectra * lambda * EQE(lambda))
Plot self.rawEQE and self.corrEQE on top of a spectrum
obsolete use EQE.Jint calculate total power of spectra and Jsc of each junction from multi-dimentional EQE
- integrate multidimentional QE(lambda)(junction) times MD reference spectra Pspec(lambda)(ispec)
- external quantum efficiency QE[unitless] x-units = nm,
- reference spectra Pspec[W/m2/nm] x-units = nm
- optionally Pspec as string 'space', 'global', or 'direct'
- xEQE in nm, can optionally use (start, step) for equally spaced data
- default x values for Pspec from wvl
output:
- Jsc[junc,spectrum] = int(Pspec[spectrum]*EQE[junc]*lambda)
- total power=int(Pspec) if EQE is None
obsolte use EQE.Jdb calculate detailed-balance reverse saturation current from EQE vs xEQE
- xEQE[=]nm
- can optionally use (start, step) for equally spaced data
- debug on bplot
return the detailed balance dark current (see Geisz EL&LC paper, King EUPVSEC) assuming a square EQE
- Eg[=]eV
- TC[=]C
- returns Jdb[=]A/cm2
optional parameters
- method: 'gamma'
- dbsides: single-sided->1. bifacial->2.
return the bandgap from the Jdb
- assuming a square EQE
- iterates using gammaInc(3,x)=2exp(-x)(1+x+x^2/2)
optional parameters:
- Eg=1.0 eV #initial guess
- eps=0.001 #tolerance
- itermax=100 #maximum iterations
- dbsides=1. #bifacial->2.
Energy yield (EY) typical meterological year (TMY) at a specific location
Currently imports US proxy spectra from https://github.com/Ripalda/Tandems
Expects 'Tandems' github to be parallel to 'PVcircuit' github
string Name of this TMY
boolean tilt=True, axis=False
scalar
scalar
scalar
scalar
scalar
numpy.array Spectral irradiance each spectrum as a function of wavelength(wvl) 2D [nspecs][nlambda]
numpy.array Ambient temperature associate with each spectrum 1D [nspecs]
numpy.array Cell temperature associate with each spectrum 1D [nspecs]
numpy.array Wind speed associate with each spectrum 1D [nspecs]
numpy.array Fractional time associate with each spectrum 1D [nspecs]
numpy.array Angle associate with each spectrum 1D [nspecs]
numpy.array Angle modifier factor associate with each spectrum 1D [nspecs]
numpy.array Optical power associate with each spectrum 1D [nspecs]
numpy.array Optical power associate with each reference spectrum 1D [3]
numpy.array (SpecPower * NTime) associate with each spectrum 1D [nspecs]
scalar Yearly Optical Energy Resource [kWh/m2/yr]
Calculate subcell currents under TMY for a given EQE class or standard test conditions (if STC=True)
Creates numpy.array for subsequent calculations
- self.JscSTCs[refspec,junc] if STC=True
- self.Jscs[spec,junc]
Calculate Egs and Jdbs under TMY for a given EQE class
Creates numpy.array for subsequent calculations
- self.Jdbs[junc]
- self.Eg[junc]
Calculate efficiency of a cell under a reference spectrum self.JscSTCs and self.Egs must be calculate first.
Inputs
- cell 'model' can be 'Multi2T' or 'Tandem3T' objects
- 'oper' describes operation method unconstrained 'MPP', series-connected 'CM', parallel-configurations 'VM21', etc
- iref = 0 -> space
- iref = 1 -> global
- iref = 2 -> direct
Outputs
- STCeff efficiency of cell under reference spectrum (space,global,direct)
Calculate efficiency of a cell under self (TMY). self.Jscs and self.Egs must be calculate first.
Inputs
- cell 'model' can be 'Multi2T' or 'Tandem3T'
- 'oper' describes operation method unconstrained 'MPP', series-connected 'CM', parallel-configurations 'VM'
Outputs
- EY energy yield of cell [kWh/m2/yr]
- EYeff energy yield efficiency = EY/YearlyEnergy
Calculates approximate loss factor for VM strings of 3T tandems
generate a list of VM configurations + 'MPP'=4T and 'CM'=2T
mmax < 10 for formating reasons
return description of model and operation
- cell 'model' can be 'Multi2T' or 'Tandem3T'
- 'oper' describes operation method unconstrained 'MPP', series-connected 'CM', parallel-configurations 'VM'
Outputs: (bot, top, ratio, type3T)