Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
26 changes: 7 additions & 19 deletions pvlib/modelchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -1572,11 +1572,13 @@ def _prepare_temperature(self, data=None):
"""
poa = _irrad_for_celltemp(self.results.total_irrad,
self.results.effective_irradiance)
if not isinstance(data, tuple) and self.system.num_arrays > 1:
# handle simple case first, single array, data not iterable
if not isinstance(data, tuple) and self.system.num_arrays == 1:
return self._prepare_temperature_single_array(data, poa)
if not isinstance(data, tuple):
# broadcast data to all arrays
data = (data,) * self.system.num_arrays
elif not isinstance(data, tuple):
return self._prepare_temperature_single_array(data, poa)
# find where cell or module temperature is specified in input data
given_cell_temperature = tuple(itertools.starmap(
self._get_cell_temperature,
zip(data, poa, self.system.temperature_model_parameters)
Expand All @@ -1588,22 +1590,7 @@ def _prepare_temperature(self, data=None):
return self
# Calculate cell temperature from weather data. If cell_temperature
# has not been provided for some arrays then it is computed with
# ModelChain.temperature_model(). Because this operates on all Arrays
# simultaneously, 'poa_global' must be known for all arrays, including
# those that have a known cell temperature.
try:
self._verify_df(self.results.total_irrad, ['poa_global'])
except ValueError:
# Provide a more informative error message. Because only
# run_model_from_effective_irradiance() can get to this point
# without known POA we can suggest a very specific remedy in the
# error message.
raise ValueError("Incomplete input data. Data must contain "
"'poa_global'. For systems with multiple Arrays "
"if you have provided 'cell_temperature' for "
"only a subset of Arrays you must provide "
"'poa_global' for all Arrays, including those "
"that have a known 'cell_temperature'.")
# ModelChain.temperature_model().
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
# ModelChain.temperature_model().

self.temperature_model()
# replace calculated cell temperature with temperature given in `data`
# where available.
Expand Down Expand Up @@ -1814,6 +1801,7 @@ def run_model_from_effective_irradiance(self, data=None):
"""
data = _to_tuple(data)
self._check_multiple_input(data)
self._verify_df(data, required=['effective_irradiance'])
self._assign_weather(data)
self._assign_total_irrad(data)
self.results.effective_irradiance = _tuple_from_dfs(
Expand Down
44 changes: 24 additions & 20 deletions pvlib/tests/test_modelchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -985,26 +985,46 @@ def test_run_model_from_poa_tracking(sapm_dc_snl_ac_system, location,
assert_series_equal(ac, expected)


@pytest.mark.parametrize("input_type", [lambda x: x[0], tuple, list])
def test_run_model_from_effective_irradiance(sapm_dc_snl_ac_system, location,
weather, total_irrad):
weather, total_irrad, input_type):
data = weather.copy()
data[['poa_global', 'poa_diffuse', 'poa_direct']] = total_irrad
data['effective_irradiance'] = data['poa_global']
mc = ModelChain(sapm_dc_snl_ac_system, location, aoi_model='no_loss',
spectral_model='no_loss')
ac = mc.run_model_from_effective_irradiance(data).results.ac
ac = mc.run_model_from_effective_irradiance(input_type((data,))).results.ac
expected = pd.Series(np.array([149.280238, 96.678385]),
index=data.index)
assert_series_equal(ac, expected)
# check with data as an iterable of length 1
mc.run_model_from_effective_irradiance(input_type((data,)))
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
# check with data as an iterable of length 1
mc.run_model_from_effective_irradiance(input_type((data,)))



@pytest.mark.parametrize("input_type", [tuple, list])
def test_run_model_from_effective_irradiance_input_type(
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
def test_run_model_from_effective_irradiance_input_type(
def test_run_model_from_effective_irradiance_multi_array(

sapm_dc_snl_ac_system_Array, location, weather, total_irrad,
input_type):
data = weather.copy()
data[['poa_global', 'poa_diffuse', 'poa_direct']] = total_irrad
data['effective_irradiance'] = data['poa_global']
mc = ModelChain(sapm_dc_snl_ac_system_Array, location, aoi_model='no_loss',
spectral_model='no_loss')
mc.run_model_from_effective_irradiance(input_type((data, data)))
# arrays have different orientation, but should give same dc power
# because we are the same passing POA irradiance and air
# temperature.
assert_frame_equal(mc.results.dc[0], mc.results.dc[1])


@pytest.mark.parametrize("input_type", [lambda x: x[0], tuple, list])
def test_run_model_from_effective_irradiance_no_poa_global(
sapm_dc_snl_ac_system, location, weather, total_irrad):
sapm_dc_snl_ac_system, location, weather, total_irrad, input_type):
data = weather.copy()
data['effective_irradiance'] = total_irrad['poa_global']
mc = ModelChain(sapm_dc_snl_ac_system, location, aoi_model='no_loss',
spectral_model='no_loss')
ac = mc.run_model_from_effective_irradiance(data).results.ac
ac = mc.run_model_from_effective_irradiance(input_type((data,))).results.ac
expected = pd.Series(np.array([149.280238, 96.678385]),
index=data.index)
assert_series_equal(ac, expected)
Expand Down Expand Up @@ -1087,22 +1107,6 @@ def test_run_model_from_effective_irradiance_minimal_input(
assert not mc.results.ac.empty


def test_run_model_from_effective_irradiance_missing_poa(
sapm_dc_snl_ac_system_Array, location, total_irrad):
data_incomplete = pd.DataFrame(
{'effective_irradiance': total_irrad['poa_global'],
'poa_global': total_irrad['poa_global']},
index=total_irrad.index)
data_complete = pd.DataFrame(
{'effective_irradiance': total_irrad['poa_global'],
'cell_temperature': 30},
index=total_irrad.index)
mc = ModelChain(sapm_dc_snl_ac_system_Array, location)
with pytest.raises(ValueError,
match="you must provide 'poa_global' for all Arrays"):
mc.run_model_from_effective_irradiance(
(data_complete, data_incomplete))


def test_run_model_singleton_weather_single_array(cec_dc_snl_ac_system,
location, weather):
Expand Down