0
# Inverter Models
1
2
DC-to-AC power conversion models for photovoltaic inverters. Includes multiple inverter efficiency models from empirical (Sandia) to physics-based (ADR) to simplified (PVWatts) approaches, enabling accurate AC power prediction across different operating conditions.
3
4
## Capabilities
5
6
### Sandia Inverter Model
7
8
Empirical inverter model developed by Sandia National Laboratories for grid-connected PV inverters. Provides detailed efficiency modeling with voltage and power dependencies.
9
10
```python { .api }
11
def sandia(v_dc, p_dc, inverter):
12
"""
13
Sandia Grid-Connected PV Inverter model.
14
15
Parameters:
16
- v_dc: numeric, DC voltage input to the inverter (V)
17
- p_dc: numeric, DC power input to the inverter (W)
18
- inverter: dict, inverter parameters containing:
19
- Paco: AC power rating (W)
20
- Pdco: DC power input that results in Paco output at Vdco (W)
21
- Vdco: DC voltage at which AC power rating is achieved (V)
22
- Pso: DC power required to start inversion process (W)
23
- C0: curvature parameter (1/W)
24
- C1: empirical coefficient for Pdco voltage variation (1/V)
25
- C2: empirical coefficient for Pso voltage variation (1/V)
26
- C3: empirical coefficient for C0 voltage variation (1/V)
27
- Pnt: AC power consumed at night (W)
28
29
Returns:
30
- power_ac: numeric, AC power output (W)
31
"""
32
33
def sandia_multi(v_dc, p_dc, inverter):
34
"""
35
Sandia model for inverters with multiple MPPT inputs.
36
37
Parameters:
38
- v_dc: tuple/list/array, DC voltage on each MPPT input (V)
39
- p_dc: tuple/list/array, DC power on each MPPT input (W)
40
- inverter: dict, inverter parameters (same as sandia)
41
42
Returns:
43
- power_ac: numeric, AC power output for the inverter (W)
44
"""
45
```
46
47
### ADR Inverter Model
48
49
Anton Driesse's efficiency model providing detailed inverter characterization based on input voltage and power dependencies with physical basis.
50
51
```python { .api }
52
def adr(v_dc, p_dc, inverter, vtol=0.10):
53
"""
54
ADR grid-connected inverter efficiency model.
55
56
Parameters:
57
- v_dc: numeric, DC voltage input to the inverter (V)
58
- p_dc: numeric, DC power input to the inverter (W)
59
- inverter: dict, inverter parameters containing:
60
- Pnom: nominal DC power (W)
61
- Vnom: nominal DC input voltage (V)
62
- Vmax: maximum DC input voltage (V)
63
- Vmin: minimum DC input voltage (V)
64
- Vdcmax: maximum voltage supplied from DC array (V)
65
- MPPTHi: maximum DC voltage for MPPT range (V)
66
- MPPTLow: minimum DC voltage for MPPT range (V)
67
- Pacmax: maximum AC output power (W)
68
- ADRCoefficients: list of 9 coefficients for loss modeling
69
- Pnt: AC power consumed at night (W)
70
- vtol: numeric, voltage tolerance for extrapolation (0-1)
71
72
Returns:
73
- power_ac: numeric, AC power output (W)
74
"""
75
```
76
77
### PVWatts Inverter Model
78
79
NREL's simplified PVWatts inverter model used in the popular PVWatts calculator. Provides good accuracy with minimal parameters.
80
81
```python { .api }
82
def pvwatts(pdc, pdc0, eta_inv_nom=0.96, eta_inv_ref=0.9637):
83
"""
84
NREL's PVWatts inverter model.
85
86
Parameters:
87
- pdc: numeric, DC power input (W)
88
- pdc0: numeric, DC input limit of the inverter (W)
89
- eta_inv_nom: numeric, nominal inverter efficiency (default 0.96)
90
- eta_inv_ref: numeric, reference efficiency (default 0.9637)
91
92
Returns:
93
- power_ac: numeric, AC power output (W)
94
"""
95
96
def pvwatts_multi(pdc, pdc0, eta_inv_nom=0.96, eta_inv_ref=0.9637):
97
"""
98
PVWatts model extended for multiple MPP inputs.
99
100
Parameters:
101
- pdc: tuple/list/array, DC power on each MPPT input (W)
102
- pdc0: numeric, total DC power limit of the inverter (W)
103
- eta_inv_nom: numeric, nominal inverter efficiency
104
- eta_inv_ref: numeric, reference efficiency
105
106
Returns:
107
- power_ac: numeric, AC power output (W)
108
"""
109
```
110
111
### Parameter Fitting
112
113
Function for fitting Sandia inverter model parameters from measured performance data.
114
115
```python { .api }
116
def fit_sandia(ac_power, dc_power, dc_voltage, dc_voltage_level, p_ac_0, p_nt):
117
"""
118
Determine parameters for Sandia inverter model from measured data.
119
120
Parameters:
121
- ac_power: array-like, AC power output at each data point (W)
122
- dc_power: array-like, DC power input at each data point (W)
123
- dc_voltage: array-like, DC input voltage at each data point (V)
124
- dc_voltage_level: array-like, voltage level ('Vmin', 'Vnom', 'Vmax')
125
- p_ac_0: float, rated AC power of the inverter (W)
126
- p_nt: float, night tare power consumption (W)
127
128
Returns:
129
- dict, Sandia inverter model parameters
130
"""
131
```
132
133
## Usage Examples
134
135
### Basic Sandia Inverter Model
136
137
```python
138
import pvlib
139
from pvlib import inverter, pvsystem
140
import numpy as np
141
142
# Get inverter parameters from SAM database
143
inverters = pvsystem.retrieve_sam('CECInverter')
144
inverter_name = 'SMA_America__SB240_240V__CEC_2012_'
145
inv_params = inverters[inverter_name]
146
147
# Operating conditions
148
dc_voltage = np.array([300, 350, 400, 450, 500]) # V
149
dc_power = np.array([1000, 2000, 3000, 4000, 5000]) # W
150
151
# Calculate AC power using Sandia model
152
ac_power = inverter.sandia(
153
v_dc=dc_voltage,
154
p_dc=dc_power,
155
inverter=inv_params
156
)
157
158
print("Sandia Inverter Model Results:")
159
print("DC Power (W) DC Voltage (V) AC Power (W) Efficiency (%)")
160
for i in range(len(dc_power)):
161
efficiency = ac_power[i] / dc_power[i] * 100 if dc_power[i] > 0 else 0
162
print(f"{dc_power[i]:9.0f} {dc_voltage[i]:11.0f} {ac_power[i]:9.0f} {efficiency:11.1f}")
163
```
164
165
### Multi-Input Inverter Example
166
167
```python
168
import pvlib
169
from pvlib import inverter, pvsystem
170
import numpy as np
171
172
# Multi-MPPT inverter
173
inverters = pvsystem.retrieve_sam('CECInverter')
174
inv_params = inverters['SMA_America__SB240_240V__CEC_2012_']
175
176
# Two MPPT inputs with different conditions
177
# MPPT 1: Higher power
178
v_dc_1 = np.array([380, 385, 390, 395, 400])
179
p_dc_1 = np.array([1500, 1800, 2000, 2200, 2400])
180
181
# MPPT 2: Lower power
182
v_dc_2 = np.array([350, 355, 360, 365, 370])
183
p_dc_2 = np.array([800, 1000, 1200, 1400, 1600])
184
185
# Combined inputs
186
v_dc_inputs = (v_dc_1, v_dc_2)
187
p_dc_inputs = (p_dc_1, p_dc_2)
188
189
# Calculate AC power for multi-input inverter
190
ac_power_multi = inverter.sandia_multi(
191
v_dc=v_dc_inputs,
192
p_dc=p_dc_inputs,
193
inverter=inv_params
194
)
195
196
# Compare with sum of individual calculations
197
ac_power_1 = inverter.sandia(v_dc_1, p_dc_1, inv_params)
198
ac_power_2 = inverter.sandia(v_dc_2, p_dc_2, inv_params)
199
ac_power_sum = ac_power_1 + ac_power_2
200
201
print("Multi-MPPT vs Individual MPPT Comparison:")
202
print("P1(W) P2(W) Total_DC(W) Multi_AC(W) Sum_AC(W) Difference(W)")
203
for i in range(len(p_dc_1)):
204
total_dc = p_dc_1[i] + p_dc_2[i]
205
diff = ac_power_multi[i] - ac_power_sum[i]
206
print(f"{p_dc_1[i]:4.0f} {p_dc_2[i]:4.0f} {total_dc:9.0f} {ac_power_multi[i]:8.0f} {ac_power_sum[i]:7.0f} {diff:10.1f}")
207
```
208
209
### PVWatts Simple Model
210
211
```python
212
import pvlib
213
from pvlib import inverter
214
import numpy as np
215
import matplotlib.pyplot as plt
216
217
# System parameters
218
pdc0 = 5000 # DC power rating (W)
219
eta_inv_nom = 0.96 # Nominal efficiency
220
eta_inv_ref = 0.9637 # Reference efficiency
221
222
# DC power range
223
pdc = np.linspace(0, 6000, 100)
224
225
# Calculate AC power and efficiency
226
pac = inverter.pvwatts(pdc, pdc0, eta_inv_nom, eta_inv_ref)
227
efficiency = np.divide(pac, pdc, out=np.zeros_like(pac), where=pdc!=0)
228
229
# Plot inverter efficiency curve
230
plt.figure(figsize=(10, 6))
231
plt.subplot(1, 2, 1)
232
plt.plot(pdc/1000, pac/1000, 'b-', linewidth=2)
233
plt.xlabel('DC Power (kW)')
234
plt.ylabel('AC Power (kW)')
235
plt.title('PVWatts Inverter Power Curve')
236
plt.grid(True)
237
238
plt.subplot(1, 2, 2)
239
plt.plot(pdc/pdc0*100, efficiency*100, 'r-', linewidth=2)
240
plt.xlabel('DC Power (% of Rating)')
241
plt.ylabel('Efficiency (%)')
242
plt.title('PVWatts Inverter Efficiency')
243
plt.grid(True)
244
plt.ylim([90, 98])
245
246
plt.tight_layout()
247
plt.show()
248
249
print("PVWatts Inverter Performance:")
250
print("Load (%) DC Power (W) AC Power (W) Efficiency (%)")
251
for load_pct in [10, 20, 30, 50, 75, 100, 110]:
252
pdc_test = pdc0 * load_pct / 100
253
pac_test = inverter.pvwatts(pdc_test, pdc0, eta_inv_nom, eta_inv_ref)
254
eff_test = pac_test / pdc_test * 100 if pdc_test > 0 else 0
255
print(f"{load_pct:6.0f} {pdc_test:8.0f} {pac_test:8.0f} {eff_test:9.2f}")
256
```
257
258
### ADR Model Example
259
260
```python
261
import pvlib
262
from pvlib import inverter, pvsystem
263
import numpy as np
264
265
# Get ADR inverter parameters (if available in database)
266
# For demonstration, create example parameters
267
adr_params = {
268
'Pnom': 5000, # W
269
'Vnom': 400, # V
270
'Vmax': 600, # V
271
'Vmin': 200, # V
272
'Vdcmax': 600, # V
273
'MPPTHi': 550, # V
274
'MPPTLow': 250, # V
275
'Pacmax': 5000, # W
276
'ADRCoefficients': [0.01, 0.02, 0.001, 0.001, 0.0001, 0.00001, 0.1, 0.01, 0.001],
277
'Pnt': 5 # W
278
}
279
280
# Operating conditions
281
dc_voltage = np.linspace(250, 550, 10)
282
dc_power = 3000 # W constant power
283
284
# Calculate AC power using ADR model
285
ac_power_adr = inverter.adr(
286
v_dc=dc_voltage,
287
p_dc=dc_power,
288
inverter=adr_params,
289
vtol=0.10
290
)
291
292
# Calculate efficiency
293
efficiency_adr = ac_power_adr / dc_power * 100
294
295
print("ADR Inverter Model - Voltage Dependency:")
296
print("DC Voltage (V) AC Power (W) Efficiency (%)")
297
for i, v in enumerate(dc_voltage):
298
print(f"{v:11.0f} {ac_power_adr[i]:9.0f} {efficiency_adr[i]:11.2f}")
299
300
# Test at different power levels
301
dc_power_range = np.linspace(500, 5500, 10)
302
dc_voltage_fixed = 400 # V
303
304
ac_power_adr_power = inverter.adr(
305
v_dc=dc_voltage_fixed,
306
p_dc=dc_power_range,
307
inverter=adr_params
308
)
309
310
efficiency_adr_power = ac_power_adr_power / dc_power_range * 100
311
312
print("\nADR Inverter Model - Power Dependency:")
313
print("DC Power (W) AC Power (W) Efficiency (%)")
314
for i, p in enumerate(dc_power_range):
315
print(f"{p:9.0f} {ac_power_adr_power[i]:9.0f} {efficiency_adr_power[i]:11.2f}")
316
```
317
318
### Inverter Model Comparison
319
320
```python
321
import pvlib
322
from pvlib import inverter, pvsystem
323
import numpy as np
324
import matplotlib.pyplot as plt
325
326
# Get Sandia parameters
327
inverters = pvsystem.retrieve_sam('CECInverter')
328
sandia_params = inverters['SMA_America__SB240_240V__CEC_2012_']
329
330
# PVWatts parameters
331
pdc0_pvwatts = 5000 # W
332
333
# ADR parameters (example)
334
adr_params = {
335
'Pnom': 5000, 'Vnom': 400, 'Vmax': 600, 'Vmin': 200,
336
'Vdcmax': 600, 'MPPTHi': 550, 'MPPTLow': 250, 'Pacmax': 5000,
337
'ADRCoefficients': [0.01, 0.02, 0.001, 0.001, 0.0001, 0.00001, 0.1, 0.01, 0.001],
338
'Pnt': 5
339
}
340
341
# Test conditions
342
dc_power = np.linspace(100, 5500, 50)
343
dc_voltage = 400 # V constant
344
345
# Calculate AC power using different models
346
ac_sandia = inverter.sandia(dc_voltage, dc_power, sandia_params)
347
ac_pvwatts = inverter.pvwatts(dc_power, pdc0_pvwatts)
348
ac_adr = inverter.adr(dc_voltage, dc_power, adr_params)
349
350
# Calculate efficiencies
351
eff_sandia = np.divide(ac_sandia, dc_power, out=np.zeros_like(ac_sandia), where=dc_power>0) * 100
352
eff_pvwatts = np.divide(ac_pvwatts, dc_power, out=np.zeros_like(ac_pvwatts), where=dc_power>0) * 100
353
eff_adr = np.divide(ac_adr, dc_power, out=np.zeros_like(ac_adr), where=dc_power>0) * 100
354
355
# Plot comparison
356
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))
357
358
# Power curves
359
ax1.plot(dc_power/1000, ac_sandia/1000, 'b-', label='Sandia', linewidth=2)
360
ax1.plot(dc_power/1000, ac_pvwatts/1000, 'r--', label='PVWatts', linewidth=2)
361
ax1.plot(dc_power/1000, ac_adr/1000, 'g:', label='ADR', linewidth=2)
362
ax1.set_xlabel('DC Power (kW)')
363
ax1.set_ylabel('AC Power (kW)')
364
ax1.set_title('Inverter Models - Power Output')
365
ax1.legend()
366
ax1.grid(True)
367
368
# Efficiency curves
369
ax2.plot(dc_power/pdc0_pvwatts*100, eff_sandia, 'b-', label='Sandia', linewidth=2)
370
ax2.plot(dc_power/pdc0_pvwatts*100, eff_pvwatts, 'r--', label='PVWatts', linewidth=2)
371
ax2.plot(dc_power/pdc0_pvwatts*100, eff_adr, 'g:', label='ADR', linewidth=2)
372
ax2.set_xlabel('DC Power (% of Rating)')
373
ax2.set_ylabel('Efficiency (%)')
374
ax2.set_title('Inverter Models - Efficiency')
375
ax2.legend()
376
ax2.grid(True)
377
ax2.set_ylim([85, 98])
378
379
plt.tight_layout()
380
plt.show()
381
382
print("Inverter Model Comparison at Key Operating Points:")
383
print("DC Power (%) Sandia Eff (%) PVWatts Eff (%) ADR Eff (%)")
384
for pct in [10, 25, 50, 75, 100]:
385
idx = int(pct/100 * len(dc_power)) - 1
386
print(f"{pct:9.0f} {eff_sandia[idx]:10.2f} {eff_pvwatts[idx]:12.2f} {eff_adr[idx]:8.2f}")
387
```
388
389
### Parameter Fitting Example
390
391
```python
392
import pvlib
393
from pvlib import inverter
394
import numpy as np
395
import pandas as pd
396
397
# Simulate measured inverter performance data
398
# Typically from CEC test protocol or manufacturer data sheets
399
np.random.seed(42)
400
401
# Test voltages
402
voltage_levels = ['Vmin', 'Vnom', 'Vmax']
403
voltages = {'Vmin': 200, 'Vnom': 400, 'Vmax': 600}
404
405
# Generate synthetic test data
406
ac_power_data = []
407
dc_power_data = []
408
dc_voltage_data = []
409
voltage_level_data = []
410
411
for level in voltage_levels:
412
v_test = voltages[level]
413
# Test power levels (10%, 20%, 30%, 50%, 75%, 100% of rating)
414
p_ac_fractions = [0.1, 0.2, 0.3, 0.5, 0.75, 1.0]
415
p_ac_rated = 5000 # W
416
417
for frac in p_ac_fractions:
418
p_ac = p_ac_rated * frac
419
# Simulate corresponding DC power (with realistic efficiency)
420
efficiency = 0.95 * (1 - 0.05 * (1 - frac)) # Efficiency varies with load
421
p_dc = p_ac / efficiency
422
423
# Add some measurement noise
424
p_ac_meas = p_ac * (1 + np.random.normal(0, 0.01))
425
p_dc_meas = p_dc * (1 + np.random.normal(0, 0.01))
426
v_dc_meas = v_test * (1 + np.random.normal(0, 0.005))
427
428
ac_power_data.append(p_ac_meas)
429
dc_power_data.append(p_dc_meas)
430
dc_voltage_data.append(v_dc_meas)
431
voltage_level_data.append(level)
432
433
# Convert to arrays
434
ac_power_array = np.array(ac_power_data)
435
dc_power_array = np.array(dc_power_data)
436
dc_voltage_array = np.array(dc_voltage_data)
437
voltage_level_array = np.array(voltage_level_data)
438
439
# Inverter specifications
440
p_ac_0 = 5000 # W, rated AC power
441
p_nt = 2 # W, night tare
442
443
# Fit Sandia model parameters
444
fitted_params = inverter.fit_sandia(
445
ac_power=ac_power_array,
446
dc_power=dc_power_array,
447
dc_voltage=dc_voltage_array,
448
dc_voltage_level=voltage_level_array,
449
p_ac_0=p_ac_0,
450
p_nt=p_nt
451
)
452
453
print("Fitted Sandia Inverter Parameters:")
454
for param, value in fitted_params.items():
455
print(f"{param:5s}: {value:8.3f}")
456
457
# Validate fit by comparing measured vs modeled AC power
458
ac_power_modeled = inverter.sandia(
459
v_dc=dc_voltage_array,
460
p_dc=dc_power_array,
461
inverter=fitted_params
462
)
463
464
# Calculate fit quality
465
residuals = ac_power_array - ac_power_modeled
466
rmse = np.sqrt(np.mean(residuals**2))
467
mae = np.mean(np.abs(residuals))
468
r_squared = 1 - np.sum(residuals**2) / np.sum((ac_power_array - np.mean(ac_power_array))**2)
469
470
print(f"\nModel Fit Quality:")
471
print(f"RMSE: {rmse:.1f} W")
472
print(f"MAE: {mae:.1f} W")
473
print(f"R²: {r_squared:.4f}")
474
475
# Display comparison for a few points
476
print(f"\nMeasured vs Modeled Comparison (First 10 points):")
477
print("Voltage Level Measured AC (W) Modeled AC (W) Error (W)")
478
for i in range(10):
479
error = ac_power_array[i] - ac_power_modeled[i]
480
print(f"{voltage_level_array[i]:12s} {ac_power_array[i]:11.1f} {ac_power_modeled[i]:10.1f} {error:7.1f}")
481
```