-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add noct_sam cell temperature model to PVSystem, ModelChain #1195
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
Changes from 14 commits
74800b0
2fbd304
c3175b0
64b16bf
e176da8
5608f9a
4a1dea3
37ffb87
aab7d96
3b50f1a
3616e82
dcb6fbc
84a452c
2664783
9613bb8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -143,7 +143,8 @@ class PVSystem: | |||||||||
| Module parameters as defined by the SAPM, CEC, or other. | ||||||||||
|
|
||||||||||
| temperature_model_parameters : None, dict or Series, default None. | ||||||||||
| Temperature model parameters as defined by the SAPM, Pvsyst, or other. | ||||||||||
| Temperature model parameters as required by one of the models in | ||||||||||
| pvlib.temperature (excluding poa_global, temp_air and wind_speed). | ||||||||||
|
|
||||||||||
| modules_per_string: int or float, default 1 | ||||||||||
| See system topology discussion above. | ||||||||||
|
|
@@ -750,8 +751,6 @@ def fuentes_celltemp(self, poa_global, temp_air, wind_speed): | |||||||||
| if you want to match the PVWatts behavior, you can override it by | ||||||||||
| including a ``surface_tilt`` value in ``temperature_model_parameters``. | ||||||||||
|
|
||||||||||
| Notes | ||||||||||
| ----- | ||||||||||
| The `temp_air` and `wind_speed` parameters may be passed as tuples | ||||||||||
| to provide different values for each Array in the system. If not | ||||||||||
| passed as a tuple then the same value is used for input to each Array. | ||||||||||
|
|
@@ -781,6 +780,80 @@ def _build_kwargs_fuentes(array): | |||||||||
| ) | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| @_unwrap_single_value | ||||||||||
| def noct_sam_celltemp(self, poa_global, temp_air, wind_speed, | ||||||||||
| effective_irradiance=None): | ||||||||||
| """ | ||||||||||
| Use :py:func:`temperature.noct_sam` to calculate cell temperature. | ||||||||||
|
|
||||||||||
| Parameters | ||||||||||
| ---------- | ||||||||||
| poa_global : numeric or tuple of numeric | ||||||||||
| Total incident irradiance in W/m^2. | ||||||||||
|
|
||||||||||
| temp_air : numeric or tuple of numeric | ||||||||||
| Ambient dry bulb temperature in degrees C. | ||||||||||
|
|
||||||||||
| wind_speed : numeric or tuple of numeric | ||||||||||
| Wind speed in m/s at a height of 10 meters. | ||||||||||
|
|
||||||||||
| effective_irradiance : numeric, tuple of numeric or None. | ||||||||||
|
||||||||||
| effective_irradiance : numeric, tuple of numeric or None. | |
| effective_irradiance : numeric, tuple of numeric, or None. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| temp_model_kwargs['noct'] = \ | |
| # noct_sam required args. | |
| # bundled with kwargs for simplicity | |
| temp_model_kwargs['noct'] = \ |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| msg = ('Parameter noct and eta_m_ref are required.' | |
| msg = ('Parameters noct and eta_m_ref are required.' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -223,6 +223,18 @@ def pvwatts_dc_pvwatts_ac_fuentes_temp_system(): | |
| return system | ||
|
|
||
|
|
||
| @pytest.fixture(scope="function") | ||
| def pvwatts_dc_pvwatts_ac_noct_sam_temp_system(): | ||
| module_parameters = {'pdc0': 220, 'gamma_pdc': -0.003} | ||
| temp_model_params = {'noct': 45, 'eta_m_ref': 0.2} | ||
| inverter_parameters = {'pdc0': 220, 'eta_inv_nom': 0.95} | ||
| system = PVSystem(surface_tilt=32.2, surface_azimuth=180, | ||
| module_parameters=module_parameters, | ||
| temperature_model_parameters=temp_model_params, | ||
| inverter_parameters=inverter_parameters) | ||
| return system | ||
|
|
||
|
|
||
| @pytest.fixture(scope="function") | ||
| def system_no_aoi(cec_module_cs5p_220m, sapm_temperature_cs5p_220m, | ||
| cec_inverter_parameters): | ||
|
|
@@ -693,6 +705,23 @@ def test_run_model_with_weather_fuentes_temp(sapm_dc_snl_ac_system, location, | |
| assert not mc.results.ac.empty | ||
|
|
||
|
|
||
| def test_run_model_with_weather_noct_sam_temp(sapm_dc_snl_ac_system, location, | ||
| weather, mocker): | ||
| weather['wind_speed'] = 5 | ||
| weather['temp_air'] = 10 | ||
| sapm_dc_snl_ac_system.temperature_model_parameters = { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #1196 will need to update for this one too |
||
| 'noct': 45, 'eta_m_ref': 0.2 | ||
| } | ||
| mc = ModelChain(sapm_dc_snl_ac_system, location) | ||
| mc.temperature_model = 'noct_sam' | ||
| m_noct_sam = mocker.spy(sapm_dc_snl_ac_system, 'noct_sam_celltemp') | ||
| mc.run_model(weather) | ||
| assert m_noct_sam.call_count == 1 | ||
| assert_series_equal(m_noct_sam.call_args[0][1], weather['temp_air']) | ||
| assert_series_equal(m_noct_sam.call_args[0][2], weather['wind_speed']) | ||
| assert not mc.results.ac.empty | ||
|
|
||
|
|
||
| def test_run_model_tracker(sapm_dc_snl_ac_system, location, weather, mocker): | ||
| system = SingleAxisTracker( | ||
| module_parameters=sapm_dc_snl_ac_system.module_parameters, | ||
|
|
@@ -907,7 +936,9 @@ def test__prepare_temperature_arrays_weather(sapm_dc_snl_ac_system_same_arrays, | |
| ({'u0': 25.0, 'u1': 6.84}, | ||
| ModelChain.faiman_temp), | ||
| ({'noct_installed': 45}, | ||
| ModelChain.fuentes_temp)]) | ||
| ModelChain.fuentes_temp), | ||
| ({'noct': 45, 'eta_m_ref': 0.2}, | ||
| ModelChain.noct_sam_temp)]) | ||
| def test_temperature_models_arrays_multi_weather( | ||
| temp_params, temp_model, | ||
| sapm_dc_snl_ac_system_same_arrays, | ||
|
|
@@ -1256,16 +1287,19 @@ def test_infer_spectral_model(location, sapm_dc_snl_ac_system, | |
|
|
||
|
|
||
| @pytest.mark.parametrize('temp_model', [ | ||
| 'sapm_temp', 'faiman_temp', 'pvsyst_temp', 'fuentes_temp']) | ||
| 'sapm_temp', 'faiman_temp', 'pvsyst_temp', 'fuentes_temp', | ||
| 'noct_sam_temp']) | ||
| def test_infer_temp_model(location, sapm_dc_snl_ac_system, | ||
| pvwatts_dc_pvwatts_ac_pvsyst_temp_system, | ||
| pvwatts_dc_pvwatts_ac_faiman_temp_system, | ||
| pvwatts_dc_pvwatts_ac_fuentes_temp_system, | ||
| pvwatts_dc_pvwatts_ac_noct_sam_temp_system, | ||
| temp_model): | ||
| dc_systems = {'sapm_temp': sapm_dc_snl_ac_system, | ||
| 'pvsyst_temp': pvwatts_dc_pvwatts_ac_pvsyst_temp_system, | ||
| 'faiman_temp': pvwatts_dc_pvwatts_ac_faiman_temp_system, | ||
| 'fuentes_temp': pvwatts_dc_pvwatts_ac_fuentes_temp_system} | ||
| 'fuentes_temp': pvwatts_dc_pvwatts_ac_fuentes_temp_system, | ||
| 'noct_sam_temp': pvwatts_dc_pvwatts_ac_noct_sam_temp_system} | ||
| system = dc_systems[temp_model] | ||
| mc = ModelChain(system, location, aoi_model='physical', | ||
| spectral_model='no_loss') | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like to pass keyword arguments as keyword arguments, but I don't feel strongly about it so feel free to reject.