Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

initial implementation of pvsyst_celltemp function (#552) #628

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Dec 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions 9 docs/sphinx/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,15 @@ PVWatts model
pvsystem.pvwatts_dc
pvsystem.pvwatts_ac
pvsystem.pvwatts_losses
pvsystem.pvwatts_losses

PVsyst model
------------

.. autosummary::
:toctree: generated/

pvsystem.pvsyst_celltemp

Other
-----
Expand Down
2 changes: 2 additions & 0 deletions 2 docs/sphinx/source/whatsnew/v0.6.1.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ Enhancements
* Add warning message when :py:func:`pvlib.spa` is reloaded. (:issue:`401`)
* Add option for :py:func:`pvlib.irradiance.disc` to use relative airmass
by supplying `pressure=None`. (:issue:`449`)
* Created :py:func:`pvlib.pvsystem.pvsyst_celltemp` to implement PVsyst's cell temperature model. (:issue:`552`)


Bug fixes
Expand Down Expand Up @@ -86,4 +87,5 @@ Contributors
* Cliff Hansen (:ghuser:`cwhanse`)
* Mark Mikofski (:ghuser:`mikofski`)
* Anton Driesse (:ghuser:`adriesse`)
* Cameron Stark (:ghuser:`camerontstark`)
* Jonathan Gaffiot (:ghuser:`jgaffiot`)
81 changes: 81 additions & 0 deletions 81 pvlib/pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -1887,6 +1887,87 @@ def sapm_celltemp(poa_global, wind_speed, temp_air,
return pd.DataFrame({'temp_cell': temp_cell, 'temp_module': temp_module})


def pvsyst_celltemp(poa_global, wind_speed, temp_air, eta_m=0.1,
alpha_absorption=0.9, temp_model="freestanding"):
"""
Calculate cell temperature using the PVSyst model.

Parameters
----------
poa_global : numeric
Total incident irradiance in W/m^2.

wind_speed : numeric
Wind speed in m/s at a height of 10 meters.

temp_air : numeric
Ambient dry bulb temperature in degrees C.

eta_m : numeric
Module external efficiency as a fraction, i.e., DC power / poa_global.

alpha_absorption : float
Absorption coefficient, default is 0.9.

temp_model : string, tuple, or list, default 'freestanding' (no dict)
Model to be used.

If string, can be:

* 'freestanding' (default)
Modules with rear surfaces exposed to open air (e.g. rack
mounted).
* 'insulated'
wholmgren marked this conversation as resolved.
Show resolved Hide resolved
Modules with rear surfaces in close proximity to another
surface (e.g. roof mounted).

If tuple/list, supply parameters in the following order:

* natural_convenction_coeff : float
Natural convection coefficient. Freestanding default is 29,
fully insulated arrays is 15.

* forced_convection_coeff : float
Forced convection coefficient, default is 0.

Returns
wholmgren marked this conversation as resolved.
Show resolved Hide resolved
-------
temp_cell : numeric or Series
Cell temperature in degrees Celsius

References
----------
[1]"PVsyst 6 Help", Files.pvsyst.com, 2018. [Online]. Available:
http://files.pvsyst.com/help/index.html. [Accessed: 10- Dec- 2018].

[2] Faiman, D. (2008). "Assessing the outdoor operating temperature of
photovoltaic modules." Progress in Photovoltaics 16(4): 307-315.
"""
CameronTStark marked this conversation as resolved.
Show resolved Hide resolved

temp_models = {"freestanding": (29.0, 0), "insulated": (15.0, 0)}

if isinstance(temp_model, str):
natural_convenction_coeff, forced_convection_coeff = temp_models[
temp_model.lower()
]
elif isinstance(temp_model, (tuple, list)):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@CameronTStark in the future maybe consider duck typing instead of type checking. Even though duck typing is the Pythonic preference, it may not always work best. I think your solution here is fine, but in general I think duck typing usually results in more robust code. Eg:

else:
    natural_convenction_coeff, forced_convection_coeff = temp_model
    # already raises ValueError or TypeError
    # or use try: except to raise a more descriptive exception

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mikofski Yes, thanks for the suggestion! I've been trying to pay attention more to duck typing in my code and thought about it for this instance but since this was my first contribution and sapm_celltemp() had the Look Before You Leap type check in it already I figured I'd just follow convention.

natural_convenction_coeff, forced_convection_coeff = temp_model
else:
raise TypeError(
"Please format temp_model as a str, or tuple/list."
)

combined_convection_coeff = (
forced_convection_coeff * wind_speed
) + natural_convenction_coeff

absorption_coeff = alpha_absorption * poa_global * (1 - eta_m)
temp_difference = absorption_coeff / combined_convection_coeff
temp_cell = temp_air + temp_difference

return temp_cell


def sapm_spectral_loss(airmass_absolute, module):
"""
Calculates the SAPM spectral loss coefficient, F1.
Expand Down
40 changes: 40 additions & 0 deletions 40 pvlib/test/test_pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,46 @@ def test_PVSystem_sapm_celltemp(mocker):
assert out.shape == (1, 2)


def test_pvsyst_celltemp_default():
CameronTStark marked this conversation as resolved.
Show resolved Hide resolved
default = pvsystem.pvsyst_celltemp(900, 5, 20, 0.1)
assert_allclose(default, 45.137, 0.001)


def test_pvsyst_celltemp_non_model():
CameronTStark marked this conversation as resolved.
Show resolved Hide resolved
tup_non_model = pvsystem.pvsyst_celltemp(900, 5, 20, 0.1,
temp_model=(23.5, 6.25))
assert_allclose(tup_non_model, 33.315, 0.001)

list_non_model = pvsystem.pvsyst_celltemp(900, 5, 20, 0.1,
temp_model=[26.5, 7.68])
assert_allclose(list_non_model, 31.233, 0.001)


def test_pvsyst_celltemp_model_wrong_type():
with pytest.raises(TypeError):
pvsystem.pvsyst_celltemp(
900, 5, 20, 0.1,
temp_model={"won't": 23.5, "work": 7.68})


def test_pvsyst_celltemp_model_non_option():
with pytest.raises(KeyError):
pvsystem.pvsyst_celltemp(
900, 5, 20, 0.1,
temp_model="not_an_option")


def test_pvsyst_celltemp_with_index():
CameronTStark marked this conversation as resolved.
Show resolved Hide resolved
times = pd.DatetimeIndex(start="2015-01-01", end="2015-01-02", freq="12H")
temps = pd.Series([0, 10, 5], index=times)
irrads = pd.Series([0, 500, 0], index=times)
winds = pd.Series([10, 5, 0], index=times)

pvtemps = pvsystem.pvsyst_celltemp(irrads, winds, temps)
expected = pd.Series([0.0, 23.96551, 5.0], index=times)
assert_series_equal(expected, pvtemps)


def test_adrinverter(sam_data):
inverters = sam_data['adrinverter']
testinv = 'Ablerex_Electronics_Co___Ltd___' \
Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.