Skip to content

Commit

Permalink
yet more edits
Browse files Browse the repository at this point in the history
  • Loading branch information
cwhanse committed Oct 7, 2024
1 parent 7c80d3a commit 87da65c
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 34 deletions.
73 changes: 39 additions & 34 deletions docs/examples/snow-detection/snow-mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,27 @@
* Mode 1: Indicates periods when the system has non-uniform snow which
affects all strings. Mode 1 is assigned when both operating voltage and
current are reduced. Operating voltage is reduced when snow causes
mismatch and current is decreased due to reduced transmission.
mismatch. Current is decreased due to reduced transmission.
* Mode 2: Indicates periods when the system has non-uniform snow which
causes mismatch for some modules, but doesn't reduce light transmission
to other modules.
affects some strings, causing mismatch for some modules,
but not reducing light transmission for other modules.
* Mode 3: Indicates periods when the the system has snow that reduces
light transmission but doesn't create mismatch. Operating voltage is
consistent with snow-free conditions but current is reduced.
* Mode 4: Voltage and current are consistent with snow-free conditions.
* Mode -1: Indicates periods where it is unknown if or how snow impacts
* Mode -1: Indicates periods when it is unknown if or how snow impacts
power output. Mode -1 includes periods when:
1. Voltage modeled using measured irradiance and ideal transmission
is outside the inverter's MPPT range, OR
2. measured voltage exceeds the upper bound of the inverter's MPPT
2. Measured voltage exceeds the upper bound of the inverter's MPPT
algorithm.
Mode is None when both measured and voltage modeled from measured
irradiance are below the inverter turn-on voltage.
The procedure involves four steps:
1. Using measured plane-of-array (POA) irradiance and temperature, model
the module's maximum power current (Imp) and voltage (Vmp) assuming
that all the POA irradiance reaches the module's cells.
1. Model the module's maximum power current (Imp) and voltage (Vmp)
assuming that all the measured POA irradiance reaches the module's
cells.
2. Use the modeled Imp and measured Imp, determine the fraction of
plane-of-array irradiance that reaches the module's cells. This fraction
is called the transmittance.
Expand Down Expand Up @@ -98,7 +95,8 @@
current_col = 'INV1 CB2 Current [A]'


# %% Retrieve and print system inverter specs and DC electrical configuration
# %%
# Retrieve and print system inverter specs and DC electrical configuration

cec_inverter_db = pvlib.pvsystem.retrieve_sam('CECInverter')
my_inverter = cec_inverter_db["Yaskawa_Solectria_Solar__PVI_60TL_480__480V_"]
Expand All @@ -114,7 +112,8 @@
num_mods_per_str = 18


# %% Plot AC power relative to inverter nameplate limits. We are looking for
# %%
# Plot AC power relative to inverter nameplate limits. We are looking for
# periods of clipping, as these values are outside of MPP operating
# conditions. In these data, there is no clipping so no need to filter
# points out.
Expand All @@ -133,7 +132,8 @@
fig.tight_layout()
plt.show()

# %% Model DC voltage and power. Here we use the SAPM. Alternatively, one
# %%
# Model DC voltage and power. Here we use the SAPM. Alternatively, one
# could use a single diode model.

# SAPM coefficients derived from data from CFV Solar Test Laboratory, 2013.
Expand Down Expand Up @@ -165,7 +165,6 @@
"C7": np.nan,
}


# Model cell temperature using the SAPM model.

irrad_ref = 1000
Expand Down Expand Up @@ -233,17 +232,20 @@
ax.xaxis.set_major_formatter(date_form)

ax.plot(modeled_vmp_no_snow, '.-', c='b', fillstyle='full', label='No snow')
ax.plot(modeled_vmp_with_snow, '.-', c='r', fillstyle='full', label='With snow')
ax.plot(modeled_vmp_with_snow, '.-', c='r', fillstyle='full',
label='With snow')
ax.scatter(data.index, data[voltage_col], s=3, c='k', label='Measured')

ax.xaxis.set_major_locator(mdates.DayLocator(interval=1))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%m/%d'))

ax.axhline(mppt_high_voltage, c='r', ls='--')
ax.text(0.02, mppt_high_voltage -30, 'Maximum MPPT voltage: {} V'.format(mppt_high_voltage),
ax.text(0.02, mppt_high_voltage - 30,
'Maximum MPPT voltage: {} V'.format(mppt_high_voltage),
transform=ax.get_yaxis_transform())
ax.axhline(mppt_low_voltage, c='g', ls='--')
ax.text(0.02, mppt_low_voltage + 20, 'Minimum MPPT voltage: {} V'.format(mppt_low_voltage),
ax.text(0.02, mppt_low_voltage + 20,
'Minimum MPPT voltage: {} V'.format(mppt_low_voltage),
transform=ax.get_yaxis_transform())

ax.legend(fontsize='large')
Expand All @@ -257,6 +259,7 @@
# We write a function to assign snow categories, so that we could loop over
# additional combiner boxes.


def assign_snow_modes(voltage, current, temp_cell, effective_irradiance,
coeffs, min_dcv, max_dcv, threshold_vratio,
threshold_transmission, num_mods_per_str,
Expand Down Expand Up @@ -331,20 +334,23 @@ def assign_snow_modes(voltage, current, temp_cell, effective_irradiance,
modeled_voltage_with_ideal_transmission, min_dcv, max_dcv,
threshold_vratio, threshold_transmission)

result = pd.DataFrame(index=voltage.index, data={'transmission': T,
'modeled_voltage_with_calculated_transmission':
modeled_voltage_with_calculated_transmission,
'modeled_voltage_with_ideal_transmission':
modeled_voltage_with_ideal_transmission,
'vmp_ratio': vmp_ratio,
'mode': mode})
result = pd.DataFrame(
index=voltage.index,
data={
'transmission': T,
'modeled_voltage_with_calculated_transmission':
modeled_voltage_with_calculated_transmission,
'modeled_voltage_with_ideal_transmission':
modeled_voltage_with_ideal_transmission,
'vmp_ratio': vmp_ratio,
'mode': mode})

return result


# %%
# Demonstrate transmission, modeled voltage calculation and mode categorization
# on voltage, current pair
# on voltage, current pair.

# threshold_vratio and threshold_transmission were empirically determined
# using data collected on this system over five summers. Transmission and
Expand Down Expand Up @@ -388,7 +394,7 @@ def assign_snow_modes(voltage, current, temp_cell, effective_irradiance,
plt.show()

# %%
# Look at voltage ratio
# Look at voltage ratio.

fig, ax = plt.subplots(figsize=(10, 6))
date_form = mdates.DateFormatter("%m/%d")
Expand Down Expand Up @@ -426,7 +432,7 @@ def assign_snow_modes(voltage, current, temp_cell, effective_irradiance,


# %%
# Plot measured and modeled power, color by mode
# Plot measured and modeled power, and show snow mode with colored bars.

N = 6
alpha = 0.5
Expand Down Expand Up @@ -494,17 +500,15 @@ def assign_snow_modes(voltage, current, temp_cell, effective_irradiance,
plt.show()

# %%

# Calculate daily DC energy loss due to snow as a percentage of potential
# (modeled) DC power.
# Plot daily DC energy loss and daily snowfall totals.

# DataFrame so that we can group by days.
loss_df = pd.DataFrame(data={'modeled_power': modeled_power,
'loss_snow': loss_snow})

# We will also show daily snowfall totals for context.
# Daily snowfall is measured at 7:00 am of each day.
# Read in daily snowfall is measured at 7:00 am of each day.
# Daily snowfall will be plotted beside losses, for context.

snowfall_file = pvanalytics_dir / 'data' / 'snow_snowfall.csv'
snowfall = pd.read_csv(snowfall_file, index_col='DATE', parse_dates=True)
Expand All @@ -520,9 +524,10 @@ def assign_snow_modes(voltage, current, temp_cell, effective_irradiance,

for d in days:
temp = loss_df_gped.get_group(d)
snow_loss_daily.at[d] = 100 * temp['loss_snow'].sum() / temp['modeled_power'].sum()

snow_loss_daily.at[d] = 100 * temp['loss_snow'].sum() / \
temp['modeled_power'].sum()

# Plot daily DC energy loss and daily snowfall totals.
fig, ax = plt.subplots(figsize=(10, 6))
ax2 = ax.twinx()
snow_loss_daily.plot(kind='bar', ax=ax, width=-0.4, align='edge',
Expand Down
4 changes: 4 additions & 0 deletions pvanalytics/features/snow.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,10 @@ def categorize(transmission, measured_voltage,
Mode -1 is added in this function to cover a case that was not addressed
in [1]_.
Mode is None when measured values (voltage, current, irradiance or
temperature) are either missing or produce modeled voltage that is
invalid.
References
----------
.. [1] E. C. Cooper, J. L. Braid and L. M. Burnham, "Identifying the
Expand Down

0 comments on commit 87da65c

Please sign in to comment.