Source code for pvlib.pvsystem

import os
try:
    from urllib2 import urlopen
except ImportError:
    from urllib.request import urlopen

import numpy as np
import pandas as pd

from pvlib import tools



[docs]def systemdef(TMYmeta,SurfTilt, SurfAz,Albedo,SeriesModules,ParallelModules): ''' Generates a dict of system paramters used throughout a simulation Parameters ---------- TMYmeta : struct or dict meta file generated from a TMY file using pvl_readtmy2 or pvl_readtmy3. It should contain at least the following fields: =============== ====== ==================== meta field format description =============== ====== ==================== meta.altitude Float site elevation meta.latitude Float site latitude meta.longitude Float site longitude meta.Name String site name meta.State String state meta.TZ Float timezone =============== ====== ==================== SurfTilt : float or DataFrame Surface tilt angles in decimal degrees. SurfTilt must be >=0 and <=180. The tilt angle is defined as degrees from horizontal (e.g. surface facing up = 0, surface facing horizon = 90) SurfAz : float or DataFrame Surface azimuth angles in decimal degrees. SurfAz must be >=0 and <=360. The Azimuth convention is defined as degrees east of north (e.g. North = 0, South=180 East = 90, West = 270). Albedo : float or DataFrame Ground reflectance, typically 0.1-0.4 for surfaces on Earth (land), may increase over snow, ice, etc. May also be known as the reflection coefficient. Must be >=0 and <=1. SeriesModules : float Number of modules connected in series in a string. ParallelModules : int Number of strings connected in parallel. Returns ------- Result : dict A dict with the following fields. * 'SurfTilt' * 'SurfAz' * 'Albedo' * 'SeriesModules' * 'ParallelModules' * 'Lat' * 'Long' * 'TZ' * 'name' * 'altitude' See also -------- pvl_readtmy3 pvl_readtmy2 ''' system={'SurfTilt':SurfTilt, 'SurfAz':SurfAz, 'Albedo':Albedo, 'SeriesModules':SeriesModules, 'ParallelModules':ParallelModules, 'latitude':TMYmeta.latitude, 'longitude':TMYmeta.longitude, 'TZ':TMYmeta.TZ, 'name':TMYmeta.Name, 'altitude':TMYmeta.altitude} return system
[docs]def ashraeiam(b,theta): ''' Determine the incidence angle modifier using the ASHRAE transmission model. pvl_ashraeiam calculates the incidence angle modifier as developed in [1], and adopted by ASHRAE (American Society of Heating, Refrigeration, and Air Conditioning Engineers) [2]. The model has been used by model programs such as PVSyst [3]. Note: For incident angles near 90 degrees, this model has a discontinuity which has been addressed in this function. Parameters ---------- b : float A parameter to adjust the modifier as a function of angle of incidence. Typical values are on the order of 0.05 [3]. theta : DataFrame The angle of incidence between the module normal vector and the sun-beam vector in degrees. Theta must be a numeric scalar or vector. For any values of theta where abs(theta)>90, IAM is set to 0. For any values of theta where -90 < theta < 0, theta is set to abs(theta) and evaluated. A warning will be generated if any(theta<0 or theta>90). For values of theta near 90 degrees, the ASHRAE model may be above 1 or less than 0 due to the discontinuity of secant(theta). IAM values outside of [0,1] are set to 0 and a warning is generated. Returns ------- IAM : DataFrame The incident angle modifier calculated as 1-b*(sec(theta)-1) as described in [2,3]. IAM is a column vector with the same number of elements as the largest input vector. References ---------- [1] Souka A.F., Safwat H.H., "Determindation of the optimum orientations for the double exposure flat-plate collector and its reflections". Solar Energy vol .10, pp 170-174. 1966. [2] ASHRAE standard 93-77 [3] PVsyst Contextual Help. http://files.pvsyst.com/help/index.html?iam_loss.htm retrieved on September 10, 2012 See Also -------- pvl_getaoi pvl_ephemeris pvl_spa pvl_physicaliam ''' if any((theta < 0) | (theta >= 90)): print('Input incident angles <0 or >=90 detected For input angles with absolute value greater than 90, the ' + 'modifier is set to 0. For input angles between -90 and 0, the ' + 'angle is changed to its absolute value and evaluated.') theta[(theta < 0) | (theta >= 90)]=abs((theta < 0) | (theta >= 90)) IAM=1 - b*((1/np.cos(np.radians(theta)) - 1)) IAM[abs(theta) > 90]=0 if any((IAM > 1) | (IAM < 0)): print('It seems that we have encountered a discontinuity. Any incident angle modifiers calculated to be less than 0 or ' + 'greather than 1 have been set to 0.') IAM[((IAM > 1) | (IAM < 0))]=0 return IAM
[docs]def physicaliam(K,L,n,theta): ''' Determine the incidence angle modifier using refractive index, glazing thickness, and extinction coefficient pvl_physicaliam calculates the incidence angle modifier as described in De Soto et al. "Improvement and validation of a model for photovoltaic array performance", section 3. The calculation is based upon a physical model of absorbtion and transmission through a cover. Required information includes, incident angle, cover extinction coefficient, cover thickness Note: The authors of this function believe that eqn. 14 in [1] is incorrect. This function uses the following equation in its place: theta_r = arcsin(1/n * sin(theta)) Parameters ---------- K : float The glazing extinction coefficient in units of 1/meters. Reference [1] indicates that a value of 4 is reasonable for "water white" glass. K must be a numeric scalar or vector with all values >=0. If K is a vector, it must be the same size as all other input vectors. L : float The glazing thickness in units of meters. Reference [1] indicates that 0.002 meters (2 mm) is reasonable for most glass-covered PV panels. L must be a numeric scalar or vector with all values >=0. If L is a vector, it must be the same size as all other input vectors. n : float The effective index of refraction (unitless). Reference [1] indicates that a value of 1.526 is acceptable for glass. n must be a numeric scalar or vector with all values >=0. If n is a vector, it must be the same size as all other input vectors. theta :float The angle of incidence between the module normal vector and the sun-beam vector in degrees. Theta must be a numeric scalar or vector. For any values of theta where abs(theta)>90, IAM is set to 0. For any values of theta where -90 < theta < 0, theta is set to abs(theta) and evaluated. A warning will be generated if any(theta<0 or theta>90). Returns ------- IAM : float The incident angle modifier as specified in eqns. 14-16 of [1]. IAM is a column vector with the same number of elements as the largest input vector. References ---------- [1] W. De Soto et al., "Improvement and validation of a model for photovoltaic array performance", Solar Energy, vol 80, pp. 78-88, 2006. [2] Duffie, John A. & Beckman, William A.. (2006). Solar Engineering of Thermal Processes, third edition. [Books24x7 version] Available from http://common.books24x7.com/toc.aspx?bookid=17160. See Also -------- pvl_getaoi pvl_ephemeris pvl_spa pvl_ashraeiam ''' if any((theta < 0) | (theta >= 90)): print('Input incident angles <0 or >=90 detected For input angles with absolute value greater than 90, the ' + 'modifier is set to 0. For input angles between -90 and 0, the ' + 'angle is changed to its absolute value and evaluated.') theta[(theta < 0) | (theta >= 90)]=abs((theta < 0) | (theta >= 90)) thetar_deg=tools.asind(1.0 / n*(tools.sind(theta))) tau=np.exp(- 1.0 * (K*(L) / tools.cosd(thetar_deg)))*((1 - 0.5*((((tools.sind(thetar_deg - theta)) ** 2) / ((tools.sind(thetar_deg + theta)) ** 2) + ((tools.tand(thetar_deg - theta)) ** 2) / ((tools.tand(thetar_deg + theta)) ** 2))))) zeroang=1e-06 thetar_deg0=tools.asind(1.0 / n*(tools.sind(zeroang))) tau0=np.exp(- 1.0 * (K*(L) / tools.cosd(thetar_deg0)))*((1 - 0.5*((((tools.sind(thetar_deg0 - zeroang)) ** 2) / ((tools.sind(thetar_deg0 + zeroang)) ** 2) + ((tools.tand(thetar_deg0 - zeroang)) ** 2) / ((tools.tand(thetar_deg0 + zeroang)) ** 2))))) IAM=tau / tau0 IAM[theta == 0]=1 IAM[abs(theta) > 90 | (IAM < 0)]=0 return IAM
[docs]def calcparams_desoto(S, Tcell, alpha_isc, ModuleParameters, EgRef, dEgdT, M=1, Sref=1000, Tref=25): ''' Applies the temperature and irradiance corrections to inputs for pvl_singlediode Applies the temperature and irradiance corrections to the IL, I0, Rs, Rsh, and a parameters at reference conditions (IL_ref, I0_ref, etc.) according to the De Soto et. al description given in [1]. The results of this correction procedure may be used in a single diode model to determine IV curves at irradiance = S, cell temperature = Tcell. Parameters ---------- S : float or DataFrame The irradiance (in W/m^2) absorbed by the module. S must be >= 0. Due to a division by S in the script, any S value equal to 0 will be set to 1E-10. Tcell : float or DataFrame The average cell temperature of cells within a module in C. Tcell must be >= -273.15. alpha_isc : float The short-circuit current temperature coefficient of the module in units of 1/C. ModuleParameters : struct parameters describing PV module performance at reference conditions according to DeSoto's paper. Parameters may be generated or found by lookup. For ease of use, PVL_RETREIVESAM can automatically generate a struct based on the most recent SAM CEC module database. The ModuleParameters struct must contain (at least) the following 5 fields: *ModuleParameters.a_ref* - modified diode ideality factor parameter at reference conditions (units of eV), a_ref can be calculated from the usual diode ideality factor (n), number of cells in series (Ns), and cell temperature (Tcell) per equation (2) in [1]. *ModuleParameters.IL_ref* - Light-generated current (or photocurrent) in amperes at reference conditions. This value is referred to as Iph in some literature. *ModuleParameters.I0_ref* - diode reverse saturation current in amperes, under reference conditions. *ModuleParameters.Rsh_ref* - shunt resistance under reference conditions (ohms) *ModuleParameters.Rs_ref* - series resistance under reference conditions (ohms) EgRef : float The energy bandgap at reference temperature (in eV). 1.121 eV for silicon. EgRef must be >0. dEgdT : float The temperature dependence of the energy bandgap at SRC (in 1/C). May be either a scalar value (e.g. -0.0002677 as in [1]) or a DataFrame of dEgdT values corresponding to each input condition (this may be useful if dEgdT is a function of temperature). Other Parameters ---------------- M : float or DataFrame (optional, Default=1) An optional airmass modifier, if omitted, M is given a value of 1, which assumes absolute (pressure corrected) airmass = 1.5. In this code, M is equal to M/Mref as described in [1] (i.e. Mref is assumed to be 1). Source [1] suggests that an appropriate value for M as a function absolute airmass (AMa) may be: >>> M = np.polyval([-0.000126, 0.002816, -0.024459, 0.086257, 0.918093], AMa) M may be a DataFrame. Sref : float (optional, Default=1000) Optional reference irradiance in W/m^2. If omitted, a value of 1000 is used. Tref : float (Optional, Default=25) Optional reference cell temperature in C. If omitted, a value of 25 C is used. Returns ------- IL : float or DataFrame Light-generated current in amperes at irradiance=S and cell temperature=Tcell. I0 : float or DataFrame Diode saturation curent in amperes at irradiance S and cell temperature Tcell. Rs : float Series resistance in ohms at irradiance S and cell temperature Tcell. Rsh : float or DataFrame Shunt resistance in ohms at irradiance S and cell temperature Tcell. nNsVth : float or DataFrame Modified diode ideality factor at irradiance S and cell temperature Tcell. Note that in source [1] nNsVth = a (equation 2). nNsVth is the product of the usual diode ideality factor (n), the number of series-connected cells in the module (Ns), and the thermal voltage of a cell in the module (Vth) at a cell temperature of Tcell. References ---------- [1] W. De Soto et al., "Improvement and validation of a model for photovoltaic array performance", Solar Energy, vol 80, pp. 78-88, 2006. [2] System Advisor Model web page. https://sam.nrel.gov. [3] A. Dobos, "An Improved Coefficient Calculator for the California Energy Commission 6 Parameter Photovoltaic Module Model", Journal of Solar Energy Engineering, vol 134, 2012. [4] O. Madelung, "Semiconductors: Data Handbook, 3rd ed." ISBN 3-540-40488-0 See Also -------- pvl_sapm pvl_sapmcelltemp pvl_singlediode pvl_retreivesam Notes ----- If the reference parameters in the ModuleParameters struct are read from a database or library of parameters (e.g. System Advisor Model), it is important to use the same EgRef and dEgdT values that were used to generate the reference parameters, regardless of the actual bandgap characteristics of the semiconductor. For example, in the case of the System Advisor Model library, created as described in [3], EgRef and dEgdT for all modules were 1.121 and -0.0002677, respectively. This table of reference bandgap energies (EgRef), bandgap energy temperature dependence (dEgdT), and "typical" airmass response (M) is provided purely as reference to those who may generate their own reference module parameters (a_ref, IL_ref, I0_ref, etc.) based upon the various PV semiconductors. Again, we stress the importance of using identical EgRef and dEgdT when generation reference parameters and modifying the reference parameters (for irradiance, temperature, and airmass) per DeSoto's equations. Silicon (Si): EgRef = 1.121 dEgdT = -0.0002677 >>> M = polyval([-0.000126 0.002816 -0.024459 0.086257 0.918093], AMa) Source = Reference 1 Cadmium Telluride (CdTe): EgRef = 1.475 dEgdT = -0.0003 >>> M = polyval([-2.46E-5 9.607E-4 -0.0134 0.0716 0.9196], AMa) Source = Reference 4 Copper Indium diSelenide (CIS): EgRef = 1.010 dEgdT = -0.00011 >>> M = polyval([-3.74E-5 0.00125 -0.01462 0.0718 0.9210], AMa) Source = Reference 4 Copper Indium Gallium diSelenide (CIGS): EgRef = 1.15 dEgdT = ???? >>> M = polyval([-9.07E-5 0.0022 -0.0202 0.0652 0.9417], AMa) Source = Wikipedia Gallium Arsenide (GaAs): EgRef = 1.424 dEgdT = -0.000433 M = unknown Source = Reference 4 ''' M=np.max(M,0) a_ref=ModuleParameters.A_ref IL_ref=ModuleParameters.I_l_ref I0_ref=ModuleParameters.I_o_ref Rsh_ref=ModuleParameters.R_sh_ref Rs_ref=ModuleParameters.R_s k=8.617332478e-05 Tref_K=Tref + 273.15 Tcell_K=Tcell + 273.15 S[S == 0]=1e-10 E_g=EgRef * ((1 + dEgdT*((Tcell_K - Tref_K)))) nNsVth=a_ref*((Tcell_K / Tref_K)) IL=S / Sref *(M) *((IL_ref + alpha_isc * ((Tcell_K - Tref_K)))) I0=I0_ref * (((Tcell_K / Tref_K) ** 3)) * (np.exp((EgRef / (k*(Tref_K))) - (E_g / (k*(Tcell_K))))) Rsh=Rsh_ref * ((Sref / S)) Rs=Rs_ref return IL,I0,Rs,Rsh,nNsVth
[docs]def getaoi(SurfTilt,SurfAz,SunZen,SunAz): ''' Determine angle of incidence from surface tilt/azimuth and apparent sun zenith/azimuth The surface is defined by its tilt angle from horizontal and its azimuth pointing angle. The sun position is defined by the apparent (refraction corrected)sun zenith angle and the sun azimuth angle. Parameters ---------- SurfTilt : scalar or DataFrame of surface tilt angles in decimal degrees If SurfTilt is a DataFrame it must be of the same size as all other DataFrame inputs. SurfTilt must be >=0 and <=180. The tilt angle is defined as degrees from horizontal (e.g. surface facing up = 0, surface facing horizon = 90) SurfAz : scalar or DataFrame of the surface azimuth angles in decimal degrees If SurfAz is a DataFrame it must be of the same size as all other DataFrame inputs. SurfAz must be >=0 and <=360. The Azimuth convention is defined as degrees east of north (e.g. North = 0, East = 90, West = 270). SunZen : scalar or DataFrame of apparent (refraction-corrected) zenith angles in decimal degrees. If SunZen is a DataFrame it must be of the same size as all other DataFrame inputs. SunZen must be >=0 and <=180. SunAz : scalar or DataFrame of sun azimuth angles in decimal degrees If SunAz is a DataFrame it must be of the same size as all other DataFrame inputs. SunAz must be >=0 and <=360. The Azimuth convention is defined as degrees east of north (e.g. North = 0, East = 90, West = 270). Returns ------- AOI : DataFrame The angle, in decimal degrees, between the surface normal DataFrame and the sun beam DataFrame. References ---------- D.L. King, J.A. Kratochvil, W.E. Boyson. "Spectral and Angle-of-Incidence Effects on Photovoltaic Modules and Solar Irradiance Sensors". 26th IEEE Photovoltaic Specialists Conference. Sept. 1997. See Also -------- PVL_EPHEMERIS ''' AOI=np.degrees(np.arccos(np.cos(np.radians(SunZen))*(np.cos(np.radians(SurfTilt))) + np.sin(np.radians(SurfTilt))*(np.sin(np.radians(SunZen)))*(np.cos(np.radians(SunAz) - np.radians(SurfAz))))) #Duffie and Beckmann 1.6.3 return pd.DataFrame({'AOI':AOI})
[docs]def retreiveSAM(name,FileLoc='none'): ''' Retreive lastest module and inverter info from SAM website PVL_RETREIVESAM Retreive lastest module and inverter info from SAM website. This function will retreive either: * CEC module database * Sandia Module database * Sandia Inverter database and export it as a pandas dataframe Parameters ---------- name: String Name can be one of: * 'CECMod'- returns the CEC module database * 'SandiaInverter- returns the Sandia Inverter database * 'SandiaMod'- returns the Sandia Module database FileLoc: String Absolute path to the location of local versions of the SAM file. If FileLoc is specified, the latest versions of the SAM database will not be downloaded. The selected file must be in .csv format. If set to 'select', a dialogue will open allowing the suer to navigate to the appropriate page. Returns ------- df: DataFrame A DataFrame containing all the elements of the desired database. Each column representa a module or inverter, and a specific dataset can be retreived by the command >>> df.module_or_inverter_name Examples -------- >>> Invdb=SAM.pvl_retreiveSAM(name='SandiaInverter') >>> inverter=Invdb.AE_Solar_Energy__AE6_0__277V__277V__CEC_2012_ >>> inverter Vac 277.000000 Paco 6000.000000 Pdco 6165.670000 Vdco 361.123000 Pso 36.792300 C0 -0.000002 C1 -0.000047 C2 -0.001861 C3 0.000721 Pnt 0.070000 Vdcmax 600.000000 Idcmax 32.000000 Mppt_low 200.000000 Mppt_high 500.000000 Name: AE_Solar_Energy__AE6_0__277V__277V__CEC_2012_, dtype: float64 ''' if name=='CECMod': url='https://sam.nrel.gov/sites/sam.nrel.gov/files/sam-library-cec-modules-2014-1-14.csv' elif name=='SandiaMod': url='https://sam.nrel.gov/sites/sam.nrel.gov/files/sam-library-sandia-modules-2014-1-14.csv' elif name=='SandiaInverter': url='https://sam.nrel.gov/sites/sam.nrel.gov/files/sam-library-sandia-inverters-2014-1-14.csv' if FileLoc=='none': return read_url_to_pandas(url) elif FileLoc=='select': try: import Tkinter from tkFileDialog import askopenfilename Tkinter.Tk().withdraw() #Start interactive file input return read_relative_to_pandas(askopenfilename()) except: raise Exception ('Python not configured for TKinter. Try installing XQuartz and rerunning') else: return read_relative_to_pandas(FileLoc)
[docs]def read_url_to_pandas(url): data = urlopen(url) df=pd.read_csv(data,index_col=0) parsedindex=[] for index in df.index: parsedindex.append(index.replace(' ','_').replace('-','_').replace('.','_').replace('(','_').replace(')','_').replace('[','_').replace(']','_').replace(':','_')) df.index=parsedindex df=df.transpose() return df
[docs]def read_relative_to_pandas(FileLoc): df=pd.read_csv(FileLoc,index_col=0) parsedindex=[] for index in df.index: parsedindex.append(index.replace(' ','_').replace('-','_').replace('.','_').replace('(','_').replace(')','_').replace('[','_').replace(']','_').replace(':','_')) df.index=parsedindex df=df.transpose() return df
[docs]def sapm(Module,Eb,Ediff,Tcell,AM,AOI): ''' Performs Sandia PV Array Performance Model to get 5 points on IV curve given SAPM module parameters, Ee, and cell temperature The Sandia PV Array Performance Model (SAPM) generates 5 points on a PV module's I-V curve (Voc, Isc, Ix, Ixx, Vmp/Imp) according to SAND2004-3535. Assumes a reference cell temperature of 25 C. parameters ---------- Module : DataFrame A DataFrame defining the SAPM performance parameters (see pvl_retreivesam) Eb : float of DataFrame The effective irradiance incident upon the module (suns). Any Ee<0 are set to 0. celltemp : float of DataFrame The cell temperature (degrees C) Returns ------- Result - DataFrame A DataFrame with: * Result.Isc * Result.Imp * Result.Ix * Result.Ixx * Result.Voc * Result.Vmp * Result.Pmp Notes ----- The particular coefficients from SAPM which are required in Module are: ================ ====================================================================================================================== Module field Description ================ ====================================================================================================================== Module.c 1x8 vector with the C coefficients Module.c(1) = C0 Module.Isc0 Short circuit current at reference condition (amps) Module.Imp0 Maximum power current at reference condition (amps) Module.AlphaIsc Short circuit current temperature coefficient at reference condition (1/C) Module.AlphaImp Maximum power current temperature coefficient at reference condition (1/C) Module.BetaVoc Open circuit voltage temperature coefficient at reference condition (V/C) Module.mBetaVoc Coefficient providing the irradiance dependence for the BetaVoc temperature coefficient at reference irradiance (V/C) Module.BetaVmp Maximum power voltage temperature coefficient at reference condition Module.mBetaVmp Coefficient providing the irradiance dependence for the BetaVmp temperature coefficient at reference irradiance (V/C) Module.n Empirically determined "diode factor" (dimensionless) Module.Ns Number of cells in series in a module's cell string(s) ================ ====================================================================================================================== References ---------- [1] King, D. et al, 2004, "Sandia Photovoltaic Array Performance Model", SAND Report 3535, Sandia National Laboratories, Albuquerque, NM See Also -------- pvl_retreivesam pvl_sapmcelltemp ''' T0=25 q=1.60218e-19 k=1.38066e-23 E0=1000 AMcoeff=[Module['A4'],Module['A3'],Module['A2'],Module['A1'],Module['A0']] AOIcoeff=[Module['B5'],Module['B4'],Module['B3'],Module['B2'],Module['B1'],Module['B0']] F1 = np.polyval(AMcoeff,AM) F2 = np.polyval(AOIcoeff,AOI) Ee= F1*((Eb*F2+Module['FD']*Ediff)/E0) #var['Ee']=F1*((Eb+Ediff)/E0) #print "Ee modifed, revert for main function" Ee.fillna(0) Ee[Ee < 0]=0 Filt=Ee[Ee >= 0.001] Isc=Module.ix['Isco']*(Ee)*((1 + Module.ix['Aisc']*((Tcell - T0)))) DFOut=pd.DataFrame({'Isc':Isc}) DFOut['Imp']=Module.ix['Impo']*((Module.ix['C0']*(Ee) + Module.ix['C1'] * (Ee ** 2)))*((1 + Module.ix['Aimp']*((Tcell - T0)))) Bvoco=Module.ix['Bvoco'] + Module.ix['Mbvoc']*((1 - Ee)) delta=Module.ix['N']*(k)*((Tcell + 273.15)) / q DFOut['Voc']=(Module.ix['Voco'] + Module.ix['#Series']*(delta)*(np.log(Ee)) + Bvoco*((Tcell - T0))) Bvmpo=Module.ix['Bvmpo'] + Module.ix['Mbvmp']*((1 - Ee)) DFOut['Vmp']=(Module.ix['Vmpo'] + Module.ix['C2']*(Module.ix['#Series'])*(delta)*(np.log(Ee)) + Module.ix['C3']*(Module.ix['#Series'])*((delta*(np.log(Ee))) ** 2) + Bvmpo*((Tcell - T0))) DFOut['Vmp'][DFOut['Vmp']<0]=0 DFOut['Pmp']=DFOut.Imp*DFOut.Vmp DFOut['Ix']=Module.ix['IXO'] * (Module.ix['C4']*(Ee) + Module.ix['C5']*((Ee) ** 2))*((1 + Module.ix['Aisc']*((Tcell - T0)))) DFOut['Ixx']=Module.ix['IXXO'] * (Module.ix['C6']*(Ee) + Module.ix['C7']*((Ee) ** 2))*((1 + Module.ix['Aisc']*((Tcell - T0)))) return DFOut
[docs]def sapmcelltemp(E, Wspd, Tamb,modelt='Open_rack_cell_glassback',**kwargs): ''' Estimate cell temperature from irradiance, windspeed, ambient temperature, and module parameters (SAPM) Estimate cell and module temperatures per the Sandia PV Array Performance model (SAPM, SAND2004-3535), when given the incident irradiance, wind speed, ambient temperature, and SAPM module parameters. Parameters ---------- E : float or DataFrame Total incident irradiance in W/m^2. Must be >=0. windspeed : float or DataFrame Wind speed in m/s at a height of 10 meters. Must be >=0 Tamb : float or DataFrame Ambient dry bulb temperature in degrees C. Must be >= -273.15. Other Parameters ---------------- modelt : string Model to be used for parameters, can be: * 'Open_rack_cell_glassback' (DEFAULT) * 'Roof_mount_cell_glassback' * 'Open_rack_cell_polymerback' * 'Insulated_back_polumerback' * 'Open_rack_Polymer_thinfilm_steel' * '22X_Concentrator_tracker' a : float (optional) SAPM module parameter for establishing the upper limit for module temperature at low wind speeds and high solar irradiance (see SAPM eqn. 11). Must be a scalar.If not input, this value will be taken from the chosen model b : float (optional) SAPM module parameter for establishing the rate at which the module temperature drops as wind speed increases (see SAPM eqn. 11). Must be a scalar.If not input, this value will be taken from the chosen model deltaT : float (optional) SAPM module parameter giving the temperature difference between the cell and module back surface at the reference irradiance, E0. Must be a numeric scalar >=0. If not input, this value will be taken from the chosen model Returns -------- Tcell : float or DataFrame Cell temperatures in degrees C. Tmodule : float or DataFrame Module back temperature in degrees C. References ---------- [1] King, D. et al, 2004, "Sandia Photovoltaic Array Performance Model", SAND Report 3535, Sandia National Laboratories, Albuquerque, NM See Also -------- pvl_sapm ''' TempModel={'Open_rack_cell_glassback':[-3.47, -.0594, 3], 'Roof_mount_cell_glassback':[-2.98, -.0471, 1], 'Open_rack_cell_polymerback': [-3.56, -.0750, 3], 'Insulated_back_polumerback': [-2.81, -.0455, 0 ], 'Open_rack_Polymer_thinfilm_steel':[-3.58, -.113, 3], '22X_Concentrator_tracker':[-3.23, -.130, 13] } try: a=a b=b deltaT=deltaT except: a=TempModel[modelt][0] b=TempModel[modelt][1] deltaT=TempModel[modelt][2] E0=1000 # Reference irradiance Tmodule=E*((np.exp(a + b*Wspd))) + Tamb Tcell=Tmodule + E / E0*(deltaT) return pd.DataFrame({'Tcell':Tcell,'Tmodule':Tmodule})
[docs]def singlediode(Module,IL,I0,Rs,Rsh,nNsVth,**kwargs): ''' Solve the single-diode model to obtain a photovoltaic IV curve pvl_singlediode solves the single diode equation [1]: I = IL - I0*[exp((V+I*Rs)/(nNsVth))-1] - (V + I*Rs)/Rsh for I and V when given IL, I0, Rs, Rsh, and nNsVth (nNsVth = n*Ns*Vth) which are described later. pvl_singlediode returns a struct which contains the 5 points on the I-V curve specified in SAND2004-3535 [3]. If all IL, I0, Rs, Rsh, and nNsVth are scalar, a single curve will be returned, if any are DataFrames (of the same length), multiple IV curves will be calculated. Parameters ---------- These imput parameters can be calculated using PVL_CALCPARAMS_DESOTO from meterological data. IL : float or DataFrame Light-generated current (photocurrent) in amperes under desired IV curve conditions. I0 : float or DataFrame Diode saturation current in amperes under desired IV curve conditions. Rs : float or DataFrame Series resistance in ohms under desired IV curve conditions. Rsh : float or DataFrame Shunt resistance in ohms under desired IV curve conditions. May be a scalar or DataFrame, but DataFrames must be of same length as all other input DataFrames. nNsVth : float or DataFrame the product of three components. 1) The usual diode ideal factor (n), 2) the number of cells in series (Ns), and 3) the cell thermal voltage under the desired IV curve conditions (Vth). The thermal voltage of the cell (in volts) may be calculated as k*Tcell/q, where k is Boltzmann's constant (J/K), Tcell is the temperature of the p-n junction in Kelvin, and q is the elementary charge of an electron (coulombs). Other Parameters ---------------- NumPoints : integer Number of points in the desired IV curve (optional). Must be a finite scalar value. Non-integer values will be rounded to the next highest integer (ceil). If ceil(NumPoints) is < 2, no IV curves will be produced (i.e. Result.V and Result.I will not be generated). The default value is 0, resulting in no calculation of IV points other than those specified in [3]. Returns Result : DataFrame A DataFrame with the following fields. All fields have the same number of rows as the largest input DataFrame: * Result.Isc - short circuit current in amperes. * Result.Voc - open circuit voltage in volts. * Result.Imp - current at maximum power point in amperes. * Result.Vmp - voltage at maximum power point in volts. * Result.Pmp - power at maximum power point in watts. * Result.Ix - current, in amperes, at V = 0.5*Voc. * Result.Ixx - current, in amperes, at V = 0.5*(Voc+Vmp). Notes ----- The solution employed to solve the implicit diode equation utilizes the Lambert W function to obtain an explicit function of V=f(i) and I=f(V) as shown in [2]. References ----------- [1] S.R. Wenham, M.A. Green, M.E. Watt, "Applied Photovoltaics" ISBN 0 86758 909 4 [2] A. Jain, A. Kapoor, "Exact analytical solutions of the parameters of real solar cells using Lambert W-function", Solar Energy Materials and Solar Cells, 81 (2004) 269-277. [3] D. King et al, "Sandia Photovoltaic Array Performance Model", SAND2004-3535, Sandia National Laboratories, Albuquerque, NM See also -------- pvl_sapm pvl_calcparams_desoto ''' # Find Isc using Lambert W Isc = I_from_V(Rsh=Rsh, Rs=Rs, nNsVth=nNsVth, V=0.01, I0=I0, IL=IL) #If passed a dataframe, output a dataframe, if passed a list or scalar, #return a dict if isinstance(Rsh,pd.Series): DFOut=pd.DataFrame({'Isc':Isc}) DFOut.index=Rsh.index else: DFOut={'Isc':Isc} DFOut['Rsh']=Rsh DFOut['Rs']=Rs DFOut['nNsVth']=nNsVth DFOut['I0']=I0 DFOut['IL']=IL __,Voc_return = golden_sect_DataFrame(DFOut,0,Module.V_oc_ref*1.6,Voc_optfcn) Voc=Voc_return.copy() #create an immutable copy Pmp,Vmax = golden_sect_DataFrame(DFOut,0,Module.V_oc_ref*1.14,pwr_optfcn) Imax = I_from_V(Rsh=Rsh, Rs=Rs, nNsVth=nNsVth, V=Vmax, I0=I0, IL=IL) # Invert the Power-Current curve. Find the current where the inverted power # is minimized. This is Imax. Start the optimization at Voc/2 # Find Ix and Ixx using Lambert W Ix = I_from_V(Rsh=Rsh, Rs=Rs, nNsVth=nNsVth, V=.5*Voc, I0=I0, IL=IL) Ixx = I_from_V(Rsh=Rsh, Rs=Rs, nNsVth=nNsVth, V=0.5*(Voc+Vmax), I0=I0, IL=IL) ''' # If the user says they want a curve of with number of points equal to # NumPoints (must be >=2), then create a voltage array where voltage is # zero in the first column, and Voc in the last column. Number of columns # must equal NumPoints. Each row represents the voltage for one IV curve. # Then create a current array where current is Isc in the first column, and # zero in the last column, and each row represents the current in one IV # curve. Thus the nth (V,I) point of curve m would be found as follows: # (Result.V(m,n),Result.I(m,n)). if NumPoints >= 2 s = ones(1,NumPoints); # shaping DataFrame to shape the column DataFrame parameters into 2-D matrices Result.V = (Voc)*(0:1/(NumPoints-1):1); Result.I = I_from_V(Rsh*s, Rs*s, nNsVth*s, Result.V, I0*s, IL*s); end ''' DFOut['Imp']=Imax DFOut['Voc']=Voc DFOut['Vmp']=Vmax DFOut['Pmp']=Pmp DFOut['Ix']=Ix DFOut['Ixx']=Ixx return DFOut
''' Created April,2014 Author: Rob Andrews, Calama Consulting '''
[docs]def golden_sect_DataFrame(df,VL,VH,func): ''' Vectorized golden section search for finding MPPT from a dataframe timeseries Parameters ---------- df : DataFrame Dataframe containing a timeseries of inputs to the function to be optimized. Each row should represent an independant optimization VL: float low bound of the optimization VH: float Uppoer bound of the optimization func: function function to be optimized must be in the form f(dataframe,x) Returns ------- func(df,'V1') : DataFrame function evaluated at the optimal point df['V1']: Dataframe Dataframe of optimal points Notes ----- This funtion will find the MAXIMUM of a function ''' df['VH']=VH df['VL']=VL err=df['VH']-df['VL'] errflag=True iterations=0 while errflag: phi=(np.sqrt(5)-1)/2*(df['VH']-df['VL']) df['V1']=df['VL']+phi df['V2']=df['VH']-phi df['f1']=func(df,'V1') df['f2']=func(df,'V2') df['SW_Flag']=df['f1']>df['f2'] df['VL']=df['V2']*df['SW_Flag']+df['VL']*(~df['SW_Flag']) df['VH']=df['V1']*~df['SW_Flag']+df['VH']*(df['SW_Flag']) err=(df['V1']-df['V2']) if isinstance(df,pd.DataFrame): errflag=all(abs(err)>.01) else: errflag=(abs(err)>.01) iterations=iterations+1 if iterations >50: raise Exception("EXCEPTION:iterations exeeded maximum (50)") return func(df,'V1') , df['V1']
[docs]def pwr_optfcn(df,loc): ''' function to find power from I_from_V ''' I=I_from_V(Rsh=df['Rsh'],Rs=df['Rs'], nNsVth=df['nNsVth'], V=df[loc], I0=df['I0'], IL=df['IL']) return I*df[loc]
[docs]def Voc_optfcn(df,loc): ''' function to find V_oc from I_from_V ''' I=-abs(I_from_V(Rsh=df['Rsh'], Rs=df['Rs'], nNsVth=df['nNsVth'], V=df[loc], I0=df['I0'], IL=df['IL'])) return I
[docs]def I_from_V(Rsh, Rs, nNsVth, V, I0, IL): ''' # calculates I from V per Eq 2 Jain and Kapoor 2004 # uses Lambert W implemented in wapr_vec.m # Rsh, nVth, V, I0, IL can all be DataFrames # Rs can be a DataFrame, but should be a scalar ''' try: from scipy.special import lambertw except ImportError: raise ImportError('The I_from_V function requires scipy') argW = Rs*I0*Rsh*np.exp(Rsh*(Rs*(IL+I0)+V)/(nNsVth*(Rs+Rsh)))/(nNsVth*(Rs + Rsh)) inputterm =lambertw(argW) # Eqn. 4 in Jain and Kapoor, 2004 I = -V/(Rs + Rsh) - (nNsVth/Rs) * inputterm + Rsh*(IL + I0)/(Rs + Rsh) return I.real
[docs]def snlinverter(Inverter,Vmp,Pmp): ''' Converts DC power and voltage to AC power using Sandia's Grid-Connected PV Inverter model Determine the AC power output of an inverter given the DC voltage, DC power, and appropriate Sandia Grid-Connected Photovoltaic Inverter Model parameters. The output, ACPower, is clipped at the maximum power output, and gives a negative power during low-input power conditions, but does NOT account for maximum power point tracking voltage windows nor maximum current or voltage limits on the inverter. Parameters ---------- Inverter : DataFrame A DataFrame defining the inverter to be used, giving the inverter performance parameters according to the Sandia Grid-Connected Photovoltaic Inverter Model (SAND 2007-5036) [1]. A set of inverter performance parameters are provided with PV_LIB, or may be generated from a System Advisor Model (SAM) [2] library using pvl_retreivesam. Required DataFrame components are: ============= ============================================================================================================================================================================================== Field DataFrame ============= ============================================================================================================================================================================================== Inverter.Pac0 AC-power output from inverter based on input power and voltage, (W) Inverter.Pdc0 DC-power input to inverter, typically assumed to be equal to the PV array maximum power, (W) Inverter.Vdc0 DC-voltage level at which the AC-power rating is achieved at the reference operating condition, (V) Inverter.Ps0 DC-power required to start the inversion process, or self-consumption by inverter, strongly influences inverter efficiency at low power levels, (W) Inverter.C0 Parameter defining the curvature (parabolic) of the relationship between ac-power and dc-power at the reference operating condition, default value of zero gives a linear relationship, (1/W) Inverter.C1 Empirical coefficient allowing Pdco to vary linearly with dc-voltage input, default value is zero, (1/V) Inverter.C2 empirical coefficient allowing Pso to vary linearly with dc-voltage input, default value is zero, (1/V) Inverter.C3 empirical coefficient allowing Co to vary linearly with dc-voltage input, default value is zero, (1/V) Inverter.Pnt ac-power consumed by inverter at night (night tare) to maintain circuitry required to sense PV array voltage, (W) ============= ============================================================================================================================================================================================== Vdc : float or DataFrame DC voltages, in volts, which are provided as input to the inverter. Vdc must be >= 0. Pdc : float or DataFrame A scalar or DataFrame of DC powers, in watts, which are provided as input to the inverter. Pdc must be >= 0. Returns ------- ACPower : float or DataFrame Mdeled AC power output given the input DC voltage, Vdc, and input DC power, Pdc. When ACPower would be greater than Pac0, it is set to Pac0 to represent inverter "clipping". When ACPower would be less than Ps0 (startup power required), then ACPower is set to -1*abs(Pnt) to represent nightly power losses. ACPower is not adjusted for maximum power point tracking (MPPT) voltage windows or maximum current limits of the inverter. References ---------- [1] (SAND2007-5036, "Performance Model for Grid-Connected Photovoltaic Inverters by D. King, S. Gonzalez, G. Galbraith, W. Boyson) [2] System Advisor Model web page. https://sam.nrel.gov. See also -------- pvl_sapm pvl_samlibrary pvl_singlediode ''' Paco=Inverter['Paco'] Pdco=Inverter['Pdco'] Vdco=Inverter['Vdco'] Pso=Inverter['Pso'] C0=Inverter['C0'] C1=Inverter['C1'] C2=Inverter['C2'] C3=Inverter['C3'] Pnt=Inverter['Pnt'] A=Pdco*((1 + C1*((Vmp - Vdco)))) B=Pso*((1 + C2*((Vmp - Vdco)))) C=C0*((1 + C3*((Vmp - Vdco)))) ACPower=((Paco / (A - B)) - C*((A - B)))*((Pmp - B)) + C*((Pmp - B) ** 2) ACPower[ACPower > Paco]=Paco ACPower[ACPower < Pso]=- 1.0 * abs(Pnt) return ACPower