0
# PV System Models
1
2
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.
3
4
## Capabilities
5
6
### System Classes
7
8
High-level classes for representing complete PV systems.
9
10
```python { .api }
11
class PVSystem:
12
"""
13
Complete PV system representation with arrays and mounting.
14
15
Parameters:
16
- arrays: Array or iterable of Array objects
17
- name: str, system name
18
- inverter: dict, inverter parameters
19
- inverter_parameters: dict, inverter model parameters
20
- temperature_model_parameters: dict, temperature model parameters
21
"""
22
23
def get_irradiance(self, *args, **kwargs):
24
"""Calculate irradiance on system surfaces."""
25
26
def get_aoi(self, *args, **kwargs):
27
"""Calculate angle of incidence on system surfaces."""
28
29
class Array:
30
"""
31
Individual PV array representation.
32
33
Parameters:
34
- mount: AbstractMount object, mounting configuration
35
- albedo: numeric, ground reflectance (0-1)
36
- module: str or dict, module identifier or parameters
37
- module_type: str, module technology type
38
- module_parameters: dict, module model parameters
39
- temperature_model_parameters: dict, temperature model parameters
40
- name: str, array name
41
"""
42
43
class FixedMount:
44
"""
45
Fixed-tilt mounting system.
46
47
Parameters:
48
- surface_tilt: numeric, tilt angle in degrees from horizontal
49
- surface_azimuth: numeric, azimuth angle in degrees from north
50
- racking_model: str, racking model for temperature calculations
51
- module_height: str, module mounting height ('ground', 'roof')
52
"""
53
54
class SingleAxisTrackerMount:
55
"""
56
Single-axis tracking mounting system.
57
58
Parameters:
59
- axis_tilt: numeric, tracker axis tilt in degrees from horizontal
60
- axis_azimuth: numeric, tracker axis azimuth in degrees from north
61
- max_angle: numeric, maximum tracking angle in degrees
62
- backtrack: bool, enable backtracking
63
- gcr: numeric, ground coverage ratio
64
- cross_axis_tilt: numeric, cross-axis tilt in degrees
65
- racking_model: str, racking model for temperature calculations
66
- module_height: str, module mounting height
67
"""
68
```
69
70
### Single Diode Models
71
72
Core photovoltaic cell and module modeling using equivalent circuit approach.
73
74
```python { .api }
75
def singlediode(photocurrent, saturation_current, resistance_series,
76
resistance_shunt, nNsVth, ivcurve_pnts=None):
77
"""
78
Single diode model for PV cells and modules.
79
80
Parameters:
81
- photocurrent: numeric, light-generated current (A)
82
- saturation_current: numeric, dark saturation current (A)
83
- resistance_series: numeric, series resistance (ohm)
84
- resistance_shunt: numeric, shunt resistance (ohm)
85
- nNsVth: numeric, thermal voltage parameter (V)
86
- ivcurve_pnts: int, number of IV curve points to calculate
87
88
Returns:
89
OrderedDict with keys:
90
- i_sc: short-circuit current (A)
91
- v_oc: open-circuit voltage (V)
92
- i_mp: maximum power point current (A)
93
- v_mp: maximum power point voltage (V)
94
- p_mp: maximum power (W)
95
- i_x: current at V = 0.5*Voc (A)
96
- i_xx: current at V = 0.5*(Voc + Vmp) (A)
97
- v: voltage array (V)
98
- i: current array (A)
99
"""
100
101
def max_power_point(photocurrent, saturation_current, resistance_series,
102
resistance_shunt, nNsVth, method='brentq'):
103
"""
104
Find maximum power point of single diode model.
105
106
Parameters:
107
- photocurrent: numeric, light-generated current (A)
108
- saturation_current: numeric, dark saturation current (A)
109
- resistance_series: numeric, series resistance (ohm)
110
- resistance_shunt: numeric, shunt resistance (ohm)
111
- nNsVth: numeric, thermal voltage parameter (V)
112
- method: str, solution method ('brentq', 'newton')
113
114
Returns:
115
OrderedDict with keys: i_mp, v_mp, p_mp
116
"""
117
118
def v_from_i(current, photocurrent, saturation_current, resistance_series,
119
resistance_shunt, nNsVth, method='lambertw'):
120
"""
121
Calculate voltage from current using single diode model.
122
123
Parameters:
124
- current: numeric, desired current (A)
125
- photocurrent: numeric, light-generated current (A)
126
- saturation_current: numeric, dark saturation current (A)
127
- resistance_series: numeric, series resistance (ohm)
128
- resistance_shunt: numeric, shunt resistance (ohm)
129
- nNsVth: numeric, thermal voltage parameter (V)
130
- method: str, solution method ('lambertw', 'newton', 'brentq')
131
132
Returns:
133
numeric, voltage (V)
134
"""
135
136
def i_from_v(voltage, photocurrent, saturation_current, resistance_series,
137
resistance_shunt, nNsVth, method='lambertw'):
138
"""
139
Calculate current from voltage using single diode model.
140
141
Parameters:
142
- voltage: numeric, desired voltage (V)
143
- photocurrent: numeric, light-generated current (A)
144
- saturation_current: numeric, dark saturation current (A)
145
- resistance_series: numeric, series resistance (ohm)
146
- resistance_shunt: numeric, shunt resistance (ohm)
147
- nNsVth: numeric, thermal voltage parameter (V)
148
- method: str, solution method ('lambertw', 'newton', 'brentq')
149
150
Returns:
151
numeric, current (A)
152
"""
153
```
154
155
### Parameter Calculation Functions
156
157
Calculate single diode model parameters from module specifications.
158
159
```python { .api }
160
def calcparams_desoto(effective_irradiance, temp_cell, alpha_sc, a_ref,
161
I_L_ref, I_o_ref, R_sh_ref, R_s, EgRef=1.121,
162
dEgdT=-0.0002677, irrad_ref=1000, temp_ref=25):
163
"""
164
Calculate single diode model parameters using De Soto method.
165
166
Parameters:
167
- effective_irradiance: numeric, effective irradiance (W/m^2)
168
- temp_cell: numeric, cell temperature (C)
169
- alpha_sc: numeric, short-circuit current temperature coefficient (A/C)
170
- a_ref: numeric, modified diode ideality factor at reference conditions
171
- I_L_ref: numeric, light current at reference conditions (A)
172
- I_o_ref: numeric, saturation current at reference conditions (A)
173
- R_sh_ref: numeric, shunt resistance at reference conditions (ohm)
174
- R_s: numeric, series resistance (ohm)
175
- EgRef: numeric, bandgap energy at reference temperature (eV)
176
- dEgdT: numeric, temperature coefficient of bandgap energy (eV/C)
177
- irrad_ref: numeric, reference irradiance (W/m^2)
178
- temp_ref: numeric, reference temperature (C)
179
180
Returns:
181
tuple: (photocurrent, saturation_current, resistance_series,
182
resistance_shunt, nNsVth)
183
"""
184
185
def calcparams_cec(effective_irradiance, temp_cell, alpha_sc, a_ref,
186
I_L_ref, I_o_ref, R_sh_ref, R_s, Adjust,
187
EgRef=1.121, dEgdT=-0.0002677, irrad_ref=1000, temp_ref=25):
188
"""
189
Calculate single diode model parameters using CEC method.
190
191
Parameters:
192
- effective_irradiance: numeric, effective irradiance (W/m^2)
193
- temp_cell: numeric, cell temperature (C)
194
- alpha_sc: numeric, short-circuit current temperature coefficient (A/C)
195
- a_ref: numeric, modified diode ideality factor at reference conditions
196
- I_L_ref: numeric, light current at reference conditions (A)
197
- I_o_ref: numeric, saturation current at reference conditions (A)
198
- R_sh_ref: numeric, shunt resistance at reference conditions (ohm)
199
- R_s: numeric, series resistance (ohm)
200
- Adjust: numeric, CEC adjustment parameter
201
- EgRef: numeric, bandgap energy at reference temperature (eV)
202
- dEgdT: numeric, temperature coefficient of bandgap energy (eV/C)
203
- irrad_ref: numeric, reference irradiance (W/m^2)
204
- temp_ref: numeric, reference temperature (C)
205
206
Returns:
207
tuple: (photocurrent, saturation_current, resistance_series,
208
resistance_shunt, nNsVth)
209
"""
210
211
def calcparams_pvsyst(effective_irradiance, temp_cell, alpha_sc, gamma_ref,
212
mu_gamma, I_L_ref, I_o_ref, R_sh_ref, R_sh_0, R_sh_exp,
213
R_s, cells_in_series, EgRef=1.121, irrad_ref=1000, temp_ref=25):
214
"""
215
Calculate single diode model parameters using PVsyst method.
216
217
Parameters:
218
- effective_irradiance: numeric, effective irradiance (W/m^2)
219
- temp_cell: numeric, cell temperature (C)
220
- alpha_sc: numeric, short-circuit current temperature coefficient (A/C)
221
- gamma_ref: numeric, diode ideality factor at reference conditions
222
- mu_gamma: numeric, temperature coefficient of gamma (1/C)
223
- I_L_ref: numeric, light current at reference conditions (A)
224
- I_o_ref: numeric, saturation current at reference conditions (A)
225
- R_sh_ref: numeric, shunt resistance at reference conditions (ohm)
226
- R_sh_0: numeric, shunt resistance at zero irradiance (ohm)
227
- R_sh_exp: numeric, shunt resistance irradiance exponent
228
- R_s: numeric, series resistance (ohm)
229
- cells_in_series: int, number of cells in series
230
- EgRef: numeric, bandgap energy at reference temperature (eV)
231
- irrad_ref: numeric, reference irradiance (W/m^2)
232
- temp_ref: numeric, reference temperature (C)
233
234
Returns:
235
tuple: (photocurrent, saturation_current, resistance_series,
236
resistance_shunt, nNsVth)
237
"""
238
```
239
240
### SAPM (Sandia Array Performance Model)
241
242
Empirical PV module performance model developed by Sandia National Laboratories.
243
244
```python { .api }
245
def sapm(effective_irradiance, temp_cell, module, *, temperature_ref=25,
246
irradiance_ref=1000):
247
"""
248
Sandia Array Performance Model for PV modules.
249
250
Parameters:
251
- effective_irradiance: numeric, effective irradiance (W/m^2)
252
- temp_cell: numeric, cell temperature (C)
253
- module: dict, module parameters containing SAPM coefficients
254
- temperature_ref: numeric, reference temperature (C)
255
- irradiance_ref: numeric, reference irradiance (W/m^2)
256
257
Returns:
258
OrderedDict with keys:
259
- i_sc: short-circuit current (A)
260
- i_mp: maximum power point current (A)
261
- v_oc: open-circuit voltage (V)
262
- v_mp: maximum power point voltage (V)
263
- p_mp: maximum power (W)
264
- i_x: current at V = 0.5*Voc (A)
265
- i_xx: current at V = 0.5*(Voc + Vmp) (A)
266
"""
267
268
def sapm_effective_irradiance(poa_direct, poa_diffuse, airmass_absolute, aoi,
269
module, reference_irradiance=1000):
270
"""
271
Calculate effective irradiance for SAPM model.
272
273
Parameters:
274
- poa_direct: numeric, direct plane-of-array irradiance (W/m^2)
275
- poa_diffuse: numeric, diffuse plane-of-array irradiance (W/m^2)
276
- airmass_absolute: numeric, absolute airmass
277
- aoi: numeric, angle of incidence (degrees)
278
- module: dict, module parameters containing SAPM coefficients
279
- reference_irradiance: numeric, reference irradiance (W/m^2)
280
281
Returns:
282
numeric, effective irradiance (W/m^2)
283
"""
284
```
285
286
### PVWatts Model
287
288
Simplified PV system model used by NREL's PVWatts calculator.
289
290
```python { .api }
291
def pvwatts_dc(effective_irradiance, temp_cell, pdc0, gamma_pdc, temp_ref=25.0):
292
"""
293
PVWatts DC power model.
294
295
Parameters:
296
- effective_irradiance: numeric, effective irradiance (W/m^2)
297
- temp_cell: numeric, cell temperature (C)
298
- pdc0: numeric, DC power at reference conditions (W)
299
- gamma_pdc: numeric, temperature coefficient of DC power (%/C)
300
- temp_ref: numeric, reference temperature (C)
301
302
Returns:
303
numeric, DC power (W)
304
"""
305
306
def pvwatts_losses(soiling=2, shading=3, snow=0, mismatch=2, wiring=2,
307
connections=0.5, lid=1.5, nameplate_rating=1, age=0,
308
availability=3):
309
"""
310
Calculate PVWatts system losses.
311
312
Parameters:
313
- soiling: numeric, soiling loss (%)
314
- shading: numeric, shading loss (%)
315
- snow: numeric, snow loss (%)
316
- mismatch: numeric, module mismatch loss (%)
317
- wiring: numeric, DC wiring loss (%)
318
- connections: numeric, DC connections loss (%)
319
- lid: numeric, light-induced degradation loss (%)
320
- nameplate_rating: numeric, nameplate rating loss (%)
321
- age: numeric, age-related degradation loss (%)
322
- availability: numeric, system availability loss (%)
323
324
Returns:
325
numeric, total loss factor (0-1)
326
"""
327
```
328
329
### System Scaling and Losses
330
331
Functions for scaling module parameters and calculating system losses.
332
333
```python { .api }
334
def scale_voltage_current_power(data, voltage=1, current=1):
335
"""
336
Scale voltage, current, and power data.
337
338
Parameters:
339
- data: dict, data containing voltage, current, and power arrays
340
- voltage: numeric, voltage scaling factor
341
- current: numeric, current scaling factor
342
343
Returns:
344
dict, scaled data
345
"""
346
347
def dc_ohmic_losses(resistance, current):
348
"""
349
Calculate DC ohmic losses.
350
351
Parameters:
352
- resistance: numeric, DC resistance (ohm)
353
- current: numeric, DC current (A)
354
355
Returns:
356
numeric, power loss (W)
357
"""
358
359
def dc_ohms_from_percent(vmp_ref, imp_ref, dc_ohmic_percent,
360
modules_per_string=1, strings=1):
361
"""
362
Convert DC loss percentage to equivalent resistance.
363
364
Parameters:
365
- vmp_ref: numeric, maximum power voltage at reference conditions (V)
366
- imp_ref: numeric, maximum power current at reference conditions (A)
367
- dc_ohmic_percent: numeric, DC ohmic loss percentage
368
- modules_per_string: int, number of modules per string
369
- strings: int, number of strings
370
371
Returns:
372
numeric, equivalent DC resistance (ohm)
373
"""
374
375
def combine_loss_factors(index, *losses, fill_method='ffill'):
376
"""
377
Combine multiple loss factors.
378
379
Parameters:
380
- index: pandas.Index, time index
381
- *losses: numeric or pandas.Series, loss factors (0-1)
382
- fill_method: str, method for filling missing values
383
384
Returns:
385
pandas.Series, combined loss factor
386
"""
387
```
388
389
### Module and Inverter Database
390
391
Access to module and inverter parameter databases.
392
393
```python { .api }
394
def retrieve_sam(name=None, path=None):
395
"""
396
Retrieve module and inverter parameters from SAM database.
397
398
Parameters:
399
- name: str, specific module or inverter name to retrieve
400
- path: str, path to SAM database file
401
402
Returns:
403
dict, database of module and/or inverter parameters
404
"""
405
```
406
407
## Usage Examples
408
409
### Basic Single Diode Model
410
411
```python
412
import pvlib
413
from pvlib import pvsystem
414
import numpy as np
415
416
# Module parameters (example crystalline silicon)
417
module_params = {
418
'alpha_sc': 0.004, # A/°C
419
'a_ref': 1.8, # Modified diode ideality factor
420
'I_L_ref': 9.5, # Light current at reference (A)
421
'I_o_ref': 2e-10, # Saturation current at reference (A)
422
'R_sh_ref': 400, # Shunt resistance at reference (Ω)
423
'R_s': 0.3 # Series resistance (Ω)
424
}
425
426
# Operating conditions
427
effective_irradiance = 800 # W/m²
428
temp_cell = 45 # °C
429
430
# Calculate single diode parameters
431
params = pvsystem.calcparams_desoto(
432
effective_irradiance=effective_irradiance,
433
temp_cell=temp_cell,
434
**module_params
435
)
436
437
# Solve single diode model
438
results = pvsystem.singlediode(*params)
439
440
print(f"Operating point:")
441
print(f"Isc: {results['i_sc']:.2f} A")
442
print(f"Voc: {results['v_oc']:.2f} V")
443
print(f"Imp: {results['i_mp']:.2f} A")
444
print(f"Vmp: {results['v_mp']:.2f} V")
445
print(f"Pmp: {results['p_mp']:.1f} W")
446
```
447
448
### SAPM Model Example
449
450
```python
451
import pvlib
452
from pvlib import pvsystem
453
import pandas as pd
454
455
# Get SAPM module parameters from database
456
modules = pvsystem.retrieve_sam('SandiaMod')
457
module_name = 'Canadian_Solar_CS5P_220M___2009_'
458
module = modules[module_name]
459
460
# Operating conditions
461
effective_irradiance = np.array([200, 400, 600, 800, 1000])
462
temp_cell = 25
463
464
# Calculate module performance using SAPM
465
results = pvsystem.sapm(
466
effective_irradiance=effective_irradiance,
467
temp_cell=temp_cell,
468
module=module
469
)
470
471
print("SAPM Results:")
472
print("Irr(W/m²) Pmp(W) Vmp(V) Imp(A)")
473
for i, irr in enumerate(effective_irradiance):
474
pmp = results['p_mp'][i]
475
vmp = results['v_mp'][i]
476
imp = results['i_mp'][i]
477
print(f"{irr:8.0f} {pmp:5.1f} {vmp:5.2f} {imp:5.2f}")
478
```
479
480
### PVWatts System Model
481
482
```python
483
import pvlib
484
from pvlib import pvsystem
485
import numpy as np
486
487
# System parameters
488
pdc0 = 5000 # DC nameplate capacity (W)
489
gamma_pdc = -0.4 # Temperature coefficient (%/°C)
490
491
# Operating conditions
492
effective_irradiance = np.array([0, 200, 400, 600, 800, 1000])
493
temp_cell = np.array([25, 30, 35, 40, 45, 50])
494
495
# Calculate DC power
496
dc_power = pvsystem.pvwatts_dc(
497
effective_irradiance=effective_irradiance,
498
temp_cell=temp_cell,
499
pdc0=pdc0,
500
gamma_pdc=gamma_pdc
501
)
502
503
# Calculate system losses
504
loss_factor = pvsystem.pvwatts_losses(
505
soiling=2,
506
shading=3,
507
mismatch=2,
508
wiring=2,
509
connections=0.5,
510
lid=1.5,
511
nameplate_rating=1,
512
age=0,
513
availability=3
514
)
515
516
# Apply losses
517
dc_power_net = dc_power * (1 - loss_factor/100)
518
519
print("PVWatts Results:")
520
print("Irr(W/m²) Tcell(°C) DC_gross(W) DC_net(W)")
521
for i in range(len(effective_irradiance)):
522
irr = effective_irradiance[i]
523
tcell = temp_cell[i]
524
dc_gross = dc_power[i]
525
dc_net = dc_power_net[i]
526
print(f"{irr:8.0f} {tcell:8.1f} {dc_gross:10.0f} {dc_net:8.0f}")
527
528
print(f"\nTotal system loss factor: {loss_factor:.1f}%")
529
```
530
531
### PV System with Tracking
532
533
```python
534
import pvlib
535
from pvlib import pvsystem, location, solarposition, tracking
536
import pandas as pd
537
538
# Define system
539
lat, lon = 35.05, -106.54 # Albuquerque, NM
540
site = location.Location(lat, lon, tz='US/Mountain', altitude=1619)
541
542
# Single-axis tracker
543
mount = pvsystem.SingleAxisTrackerMount(
544
axis_tilt=0,
545
axis_azimuth=180,
546
max_angle=60,
547
backtrack=True,
548
gcr=0.4
549
)
550
551
# Array with tracker
552
array = pvsystem.Array(
553
mount=mount,
554
module_parameters={'pdc0': 300, 'gamma_pdc': -0.4}
555
)
556
557
# System
558
system = pvsystem.PVSystem(arrays=[array])
559
560
# Time period
561
times = pd.date_range('2023-06-21', periods=24, freq='H', tz=site.tz)
562
563
# Solar position
564
solar_pos = site.get_solarposition(times)
565
566
# Tracker orientation
567
tracker_data = tracking.singleaxis(
568
apparent_zenith=solar_pos['apparent_zenith'],
569
apparent_azimuth=solar_pos['apparent_azimuth'],
570
axis_tilt=mount.axis_tilt,
571
axis_azimuth=mount.axis_azimuth,
572
max_angle=mount.max_angle,
573
backtrack=mount.backtrack,
574
gcr=mount.gcr
575
)
576
577
print("Single-axis tracker orientation:")
578
print("Time Tilt Azimuth")
579
for i in range(6, 19): # Daytime hours
580
time_str = times[i].strftime('%H:%M')
581
tilt = tracker_data['surface_tilt'].iloc[i]
582
azimuth = tracker_data['surface_azimuth'].iloc[i]
583
print(f"{time_str} {tilt:5.1f} {azimuth:5.1f}")
584
```