A comprehensive toolbox for modeling and simulating photovoltaic energy systems.
—
Complete PV system modeling including single diode models, SAPM, PVWatts, and system-level analysis. Supports various module technologies, inverter models, and system configurations for comprehensive performance analysis.
High-level classes for representing complete PV systems.
class PVSystem:
"""
Complete PV system representation with arrays and mounting.
Parameters:
- arrays: Array or iterable of Array objects
- name: str, system name
- inverter: dict, inverter parameters
- inverter_parameters: dict, inverter model parameters
- temperature_model_parameters: dict, temperature model parameters
"""
def get_irradiance(self, *args, **kwargs):
"""Calculate irradiance on system surfaces."""
def get_aoi(self, *args, **kwargs):
"""Calculate angle of incidence on system surfaces."""
class Array:
"""
Individual PV array representation.
Parameters:
- mount: AbstractMount object, mounting configuration
- albedo: numeric, ground reflectance (0-1)
- module: str or dict, module identifier or parameters
- module_type: str, module technology type
- module_parameters: dict, module model parameters
- temperature_model_parameters: dict, temperature model parameters
- name: str, array name
"""
class FixedMount:
"""
Fixed-tilt mounting system.
Parameters:
- surface_tilt: numeric, tilt angle in degrees from horizontal
- surface_azimuth: numeric, azimuth angle in degrees from north
- racking_model: str, racking model for temperature calculations
- module_height: str, module mounting height ('ground', 'roof')
"""
class SingleAxisTrackerMount:
"""
Single-axis tracking mounting system.
Parameters:
- axis_tilt: numeric, tracker axis tilt in degrees from horizontal
- axis_azimuth: numeric, tracker axis azimuth in degrees from north
- max_angle: numeric, maximum tracking angle in degrees
- backtrack: bool, enable backtracking
- gcr: numeric, ground coverage ratio
- cross_axis_tilt: numeric, cross-axis tilt in degrees
- racking_model: str, racking model for temperature calculations
- module_height: str, module mounting height
"""Core photovoltaic cell and module modeling using equivalent circuit approach.
def singlediode(photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth, ivcurve_pnts=None):
"""
Single diode model for PV cells and modules.
Parameters:
- photocurrent: numeric, light-generated current (A)
- saturation_current: numeric, dark saturation current (A)
- resistance_series: numeric, series resistance (ohm)
- resistance_shunt: numeric, shunt resistance (ohm)
- nNsVth: numeric, thermal voltage parameter (V)
- ivcurve_pnts: int, number of IV curve points to calculate
Returns:
OrderedDict with keys:
- i_sc: short-circuit current (A)
- v_oc: open-circuit voltage (V)
- i_mp: maximum power point current (A)
- v_mp: maximum power point voltage (V)
- p_mp: maximum power (W)
- i_x: current at V = 0.5*Voc (A)
- i_xx: current at V = 0.5*(Voc + Vmp) (A)
- v: voltage array (V)
- i: current array (A)
"""
def max_power_point(photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth, method='brentq'):
"""
Find maximum power point of single diode model.
Parameters:
- photocurrent: numeric, light-generated current (A)
- saturation_current: numeric, dark saturation current (A)
- resistance_series: numeric, series resistance (ohm)
- resistance_shunt: numeric, shunt resistance (ohm)
- nNsVth: numeric, thermal voltage parameter (V)
- method: str, solution method ('brentq', 'newton')
Returns:
OrderedDict with keys: i_mp, v_mp, p_mp
"""
def v_from_i(current, photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth, method='lambertw'):
"""
Calculate voltage from current using single diode model.
Parameters:
- current: numeric, desired current (A)
- photocurrent: numeric, light-generated current (A)
- saturation_current: numeric, dark saturation current (A)
- resistance_series: numeric, series resistance (ohm)
- resistance_shunt: numeric, shunt resistance (ohm)
- nNsVth: numeric, thermal voltage parameter (V)
- method: str, solution method ('lambertw', 'newton', 'brentq')
Returns:
numeric, voltage (V)
"""
def i_from_v(voltage, photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth, method='lambertw'):
"""
Calculate current from voltage using single diode model.
Parameters:
- voltage: numeric, desired voltage (V)
- photocurrent: numeric, light-generated current (A)
- saturation_current: numeric, dark saturation current (A)
- resistance_series: numeric, series resistance (ohm)
- resistance_shunt: numeric, shunt resistance (ohm)
- nNsVth: numeric, thermal voltage parameter (V)
- method: str, solution method ('lambertw', 'newton', 'brentq')
Returns:
numeric, current (A)
"""Calculate single diode model parameters from module specifications.
def calcparams_desoto(effective_irradiance, temp_cell, alpha_sc, a_ref,
I_L_ref, I_o_ref, R_sh_ref, R_s, EgRef=1.121,
dEgdT=-0.0002677, irrad_ref=1000, temp_ref=25):
"""
Calculate single diode model parameters using De Soto method.
Parameters:
- effective_irradiance: numeric, effective irradiance (W/m^2)
- temp_cell: numeric, cell temperature (C)
- alpha_sc: numeric, short-circuit current temperature coefficient (A/C)
- a_ref: numeric, modified diode ideality factor at reference conditions
- I_L_ref: numeric, light current at reference conditions (A)
- I_o_ref: numeric, saturation current at reference conditions (A)
- R_sh_ref: numeric, shunt resistance at reference conditions (ohm)
- R_s: numeric, series resistance (ohm)
- EgRef: numeric, bandgap energy at reference temperature (eV)
- dEgdT: numeric, temperature coefficient of bandgap energy (eV/C)
- irrad_ref: numeric, reference irradiance (W/m^2)
- temp_ref: numeric, reference temperature (C)
Returns:
tuple: (photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth)
"""
def calcparams_cec(effective_irradiance, temp_cell, alpha_sc, a_ref,
I_L_ref, I_o_ref, R_sh_ref, R_s, Adjust,
EgRef=1.121, dEgdT=-0.0002677, irrad_ref=1000, temp_ref=25):
"""
Calculate single diode model parameters using CEC method.
Parameters:
- effective_irradiance: numeric, effective irradiance (W/m^2)
- temp_cell: numeric, cell temperature (C)
- alpha_sc: numeric, short-circuit current temperature coefficient (A/C)
- a_ref: numeric, modified diode ideality factor at reference conditions
- I_L_ref: numeric, light current at reference conditions (A)
- I_o_ref: numeric, saturation current at reference conditions (A)
- R_sh_ref: numeric, shunt resistance at reference conditions (ohm)
- R_s: numeric, series resistance (ohm)
- Adjust: numeric, CEC adjustment parameter
- EgRef: numeric, bandgap energy at reference temperature (eV)
- dEgdT: numeric, temperature coefficient of bandgap energy (eV/C)
- irrad_ref: numeric, reference irradiance (W/m^2)
- temp_ref: numeric, reference temperature (C)
Returns:
tuple: (photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth)
"""
def calcparams_pvsyst(effective_irradiance, temp_cell, alpha_sc, gamma_ref,
mu_gamma, I_L_ref, I_o_ref, R_sh_ref, R_sh_0, R_sh_exp,
R_s, cells_in_series, EgRef=1.121, irrad_ref=1000, temp_ref=25):
"""
Calculate single diode model parameters using PVsyst method.
Parameters:
- effective_irradiance: numeric, effective irradiance (W/m^2)
- temp_cell: numeric, cell temperature (C)
- alpha_sc: numeric, short-circuit current temperature coefficient (A/C)
- gamma_ref: numeric, diode ideality factor at reference conditions
- mu_gamma: numeric, temperature coefficient of gamma (1/C)
- I_L_ref: numeric, light current at reference conditions (A)
- I_o_ref: numeric, saturation current at reference conditions (A)
- R_sh_ref: numeric, shunt resistance at reference conditions (ohm)
- R_sh_0: numeric, shunt resistance at zero irradiance (ohm)
- R_sh_exp: numeric, shunt resistance irradiance exponent
- R_s: numeric, series resistance (ohm)
- cells_in_series: int, number of cells in series
- EgRef: numeric, bandgap energy at reference temperature (eV)
- irrad_ref: numeric, reference irradiance (W/m^2)
- temp_ref: numeric, reference temperature (C)
Returns:
tuple: (photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth)
"""Empirical PV module performance model developed by Sandia National Laboratories.
def sapm(effective_irradiance, temp_cell, module, *, temperature_ref=25,
irradiance_ref=1000):
"""
Sandia Array Performance Model for PV modules.
Parameters:
- effective_irradiance: numeric, effective irradiance (W/m^2)
- temp_cell: numeric, cell temperature (C)
- module: dict, module parameters containing SAPM coefficients
- temperature_ref: numeric, reference temperature (C)
- irradiance_ref: numeric, reference irradiance (W/m^2)
Returns:
OrderedDict with keys:
- i_sc: short-circuit current (A)
- i_mp: maximum power point current (A)
- v_oc: open-circuit voltage (V)
- v_mp: maximum power point voltage (V)
- p_mp: maximum power (W)
- i_x: current at V = 0.5*Voc (A)
- i_xx: current at V = 0.5*(Voc + Vmp) (A)
"""
def sapm_effective_irradiance(poa_direct, poa_diffuse, airmass_absolute, aoi,
module, reference_irradiance=1000):
"""
Calculate effective irradiance for SAPM model.
Parameters:
- poa_direct: numeric, direct plane-of-array irradiance (W/m^2)
- poa_diffuse: numeric, diffuse plane-of-array irradiance (W/m^2)
- airmass_absolute: numeric, absolute airmass
- aoi: numeric, angle of incidence (degrees)
- module: dict, module parameters containing SAPM coefficients
- reference_irradiance: numeric, reference irradiance (W/m^2)
Returns:
numeric, effective irradiance (W/m^2)
"""Simplified PV system model used by NREL's PVWatts calculator.
def pvwatts_dc(effective_irradiance, temp_cell, pdc0, gamma_pdc, temp_ref=25.0):
"""
PVWatts DC power model.
Parameters:
- effective_irradiance: numeric, effective irradiance (W/m^2)
- temp_cell: numeric, cell temperature (C)
- pdc0: numeric, DC power at reference conditions (W)
- gamma_pdc: numeric, temperature coefficient of DC power (%/C)
- temp_ref: numeric, reference temperature (C)
Returns:
numeric, DC power (W)
"""
def pvwatts_losses(soiling=2, shading=3, snow=0, mismatch=2, wiring=2,
connections=0.5, lid=1.5, nameplate_rating=1, age=0,
availability=3):
"""
Calculate PVWatts system losses.
Parameters:
- soiling: numeric, soiling loss (%)
- shading: numeric, shading loss (%)
- snow: numeric, snow loss (%)
- mismatch: numeric, module mismatch loss (%)
- wiring: numeric, DC wiring loss (%)
- connections: numeric, DC connections loss (%)
- lid: numeric, light-induced degradation loss (%)
- nameplate_rating: numeric, nameplate rating loss (%)
- age: numeric, age-related degradation loss (%)
- availability: numeric, system availability loss (%)
Returns:
numeric, total loss factor (0-1)
"""Functions for scaling module parameters and calculating system losses.
def scale_voltage_current_power(data, voltage=1, current=1):
"""
Scale voltage, current, and power data.
Parameters:
- data: dict, data containing voltage, current, and power arrays
- voltage: numeric, voltage scaling factor
- current: numeric, current scaling factor
Returns:
dict, scaled data
"""
def dc_ohmic_losses(resistance, current):
"""
Calculate DC ohmic losses.
Parameters:
- resistance: numeric, DC resistance (ohm)
- current: numeric, DC current (A)
Returns:
numeric, power loss (W)
"""
def dc_ohms_from_percent(vmp_ref, imp_ref, dc_ohmic_percent,
modules_per_string=1, strings=1):
"""
Convert DC loss percentage to equivalent resistance.
Parameters:
- vmp_ref: numeric, maximum power voltage at reference conditions (V)
- imp_ref: numeric, maximum power current at reference conditions (A)
- dc_ohmic_percent: numeric, DC ohmic loss percentage
- modules_per_string: int, number of modules per string
- strings: int, number of strings
Returns:
numeric, equivalent DC resistance (ohm)
"""
def combine_loss_factors(index, *losses, fill_method='ffill'):
"""
Combine multiple loss factors.
Parameters:
- index: pandas.Index, time index
- *losses: numeric or pandas.Series, loss factors (0-1)
- fill_method: str, method for filling missing values
Returns:
pandas.Series, combined loss factor
"""Access to module and inverter parameter databases.
def retrieve_sam(name=None, path=None):
"""
Retrieve module and inverter parameters from SAM database.
Parameters:
- name: str, specific module or inverter name to retrieve
- path: str, path to SAM database file
Returns:
dict, database of module and/or inverter parameters
"""import pvlib
from pvlib import pvsystem
import numpy as np
# Module parameters (example crystalline silicon)
module_params = {
'alpha_sc': 0.004, # A/°C
'a_ref': 1.8, # Modified diode ideality factor
'I_L_ref': 9.5, # Light current at reference (A)
'I_o_ref': 2e-10, # Saturation current at reference (A)
'R_sh_ref': 400, # Shunt resistance at reference (Ω)
'R_s': 0.3 # Series resistance (Ω)
}
# Operating conditions
effective_irradiance = 800 # W/m²
temp_cell = 45 # °C
# Calculate single diode parameters
params = pvsystem.calcparams_desoto(
effective_irradiance=effective_irradiance,
temp_cell=temp_cell,
**module_params
)
# Solve single diode model
results = pvsystem.singlediode(*params)
print(f"Operating point:")
print(f"Isc: {results['i_sc']:.2f} A")
print(f"Voc: {results['v_oc']:.2f} V")
print(f"Imp: {results['i_mp']:.2f} A")
print(f"Vmp: {results['v_mp']:.2f} V")
print(f"Pmp: {results['p_mp']:.1f} W")import pvlib
from pvlib import pvsystem
import pandas as pd
# Get SAPM module parameters from database
modules = pvsystem.retrieve_sam('SandiaMod')
module_name = 'Canadian_Solar_CS5P_220M___2009_'
module = modules[module_name]
# Operating conditions
effective_irradiance = np.array([200, 400, 600, 800, 1000])
temp_cell = 25
# Calculate module performance using SAPM
results = pvsystem.sapm(
effective_irradiance=effective_irradiance,
temp_cell=temp_cell,
module=module
)
print("SAPM Results:")
print("Irr(W/m²) Pmp(W) Vmp(V) Imp(A)")
for i, irr in enumerate(effective_irradiance):
pmp = results['p_mp'][i]
vmp = results['v_mp'][i]
imp = results['i_mp'][i]
print(f"{irr:8.0f} {pmp:5.1f} {vmp:5.2f} {imp:5.2f}")import pvlib
from pvlib import pvsystem
import numpy as np
# System parameters
pdc0 = 5000 # DC nameplate capacity (W)
gamma_pdc = -0.4 # Temperature coefficient (%/°C)
# Operating conditions
effective_irradiance = np.array([0, 200, 400, 600, 800, 1000])
temp_cell = np.array([25, 30, 35, 40, 45, 50])
# Calculate DC power
dc_power = pvsystem.pvwatts_dc(
effective_irradiance=effective_irradiance,
temp_cell=temp_cell,
pdc0=pdc0,
gamma_pdc=gamma_pdc
)
# Calculate system losses
loss_factor = pvsystem.pvwatts_losses(
soiling=2,
shading=3,
mismatch=2,
wiring=2,
connections=0.5,
lid=1.5,
nameplate_rating=1,
age=0,
availability=3
)
# Apply losses
dc_power_net = dc_power * (1 - loss_factor/100)
print("PVWatts Results:")
print("Irr(W/m²) Tcell(°C) DC_gross(W) DC_net(W)")
for i in range(len(effective_irradiance)):
irr = effective_irradiance[i]
tcell = temp_cell[i]
dc_gross = dc_power[i]
dc_net = dc_power_net[i]
print(f"{irr:8.0f} {tcell:8.1f} {dc_gross:10.0f} {dc_net:8.0f}")
print(f"\nTotal system loss factor: {loss_factor:.1f}%")import pvlib
from pvlib import pvsystem, location, solarposition, tracking
import pandas as pd
# Define system
lat, lon = 35.05, -106.54 # Albuquerque, NM
site = location.Location(lat, lon, tz='US/Mountain', altitude=1619)
# Single-axis tracker
mount = pvsystem.SingleAxisTrackerMount(
axis_tilt=0,
axis_azimuth=180,
max_angle=60,
backtrack=True,
gcr=0.4
)
# Array with tracker
array = pvsystem.Array(
mount=mount,
module_parameters={'pdc0': 300, 'gamma_pdc': -0.4}
)
# System
system = pvsystem.PVSystem(arrays=[array])
# Time period
times = pd.date_range('2023-06-21', periods=24, freq='H', tz=site.tz)
# Solar position
solar_pos = site.get_solarposition(times)
# Tracker orientation
tracker_data = tracking.singleaxis(
apparent_zenith=solar_pos['apparent_zenith'],
apparent_azimuth=solar_pos['apparent_azimuth'],
axis_tilt=mount.axis_tilt,
axis_azimuth=mount.axis_azimuth,
max_angle=mount.max_angle,
backtrack=mount.backtrack,
gcr=mount.gcr
)
print("Single-axis tracker orientation:")
print("Time Tilt Azimuth")
for i in range(6, 19): # Daytime hours
time_str = times[i].strftime('%H:%M')
tilt = tracker_data['surface_tilt'].iloc[i]
azimuth = tracker_data['surface_azimuth'].iloc[i]
print(f"{time_str} {tilt:5.1f} {azimuth:5.1f}")Install with Tessl CLI
npx tessl i tessl/pypi-pvlib@0.13.2