Skip to content

Commit

Permalink
Pass irradiance model params to run functions (#57)
Browse files Browse the repository at this point in the history
* Allow the run functions to use the irradiance model init params

* Started working on tests: a bit of a struggle to test parallel runs

* Gave up on mocking parallel simulations: use calculated values

* Clean up
  • Loading branch information
anomam authored Jul 12, 2019
1 parent 5dd38b3 commit 1be5483
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 23 deletions.
22 changes: 16 additions & 6 deletions pvfactors/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ def run_timeseries_engine(fn_build_report, pvarray_parameters,
cls_pvarray=OrderedPVArray, cls_engine=PVEngine,
cls_irradiance=HybridPerezOrdered,
cls_vf=VFCalculator,
fast_mode_pvrow_index=None):
fast_mode_pvrow_index=None,
irradiance_model_params={}):
"""Run timeseries simulation in normal mode, and using the specified
classes.
Expand Down Expand Up @@ -67,6 +68,9 @@ def run_timeseries_engine(fn_build_report, pvarray_parameters,
If a valid pvrow index is passed, then the PVEngine fast mode
will be activated and the engine calculation will be done only
for the back surface of the selected pvrow (Default = None)
irradiance_model_params : dict, optional
Dictionary of parameters that will be passed to the irradiance model
class as kwargs at instantiation (Default = {})
Returns
-------
Expand All @@ -76,7 +80,7 @@ def run_timeseries_engine(fn_build_report, pvarray_parameters,
"""

# Instantiate classes and engine
irradiance_model = cls_irradiance()
irradiance_model = cls_irradiance(**irradiance_model_params)
vf_calculator = cls_vf()
eng = cls_engine(pvarray_parameters, cls_pvarray=cls_pvarray,
irradiance_model=irradiance_model,
Expand All @@ -99,7 +103,7 @@ def run_parallel_engine(report_builder, pvarray_parameters,
cls_pvarray=OrderedPVArray, cls_engine=PVEngine,
cls_irradiance=HybridPerezOrdered,
cls_vf=VFCalculator, fast_mode_pvrow_index=None,
n_processes=2):
irradiance_model_params={}, n_processes=2):
"""Run timeseries simulation using multiprocessing. Here, instead of a
function that will build the report, the users will need to pass a class
(or an object).
Expand Down Expand Up @@ -146,6 +150,9 @@ def run_parallel_engine(report_builder, pvarray_parameters,
If a valid pvrow index is passed, then the PVEngine fast mode
will be activated and the engine calculation will be done only
for the back surface of the selected pvrow (Default = None)
irradiance_model_params : dict, optional
Dictionary of parameters that will be passed to the irradiance model
class as kwargs at instantiation (Default = {})
n_processes : int, optional
Number of parallel processes to run for the calculation (Default = 2)
Expand Down Expand Up @@ -181,6 +188,7 @@ class (or object)
folds_cls_irradiance = [cls_irradiance] * n_processes
folds_cls_vf = [cls_vf] * n_processes
folds_fast_mode_pvrow_index = [fast_mode_pvrow_index] * n_processes
folds_irradiance_model_params = [irradiance_model_params] * n_processes
report_indices = list(range(n_processes))

# Zip all the folds together
Expand All @@ -189,7 +197,8 @@ class (or object)
folds_solar_azimuth, folds_surface_tilt,
folds_surface_azimuth, folds_albedo, folds_cls_pvarray,
folds_cls_engine, folds_cls_irradiance, folds_cls_vf,
folds_fast_mode_pvrow_index, report_indices))
folds_fast_mode_pvrow_index,
folds_irradiance_model_params, report_indices))

# Start multiprocessing
pool = Pool(n_processes)
Expand Down Expand Up @@ -231,14 +240,15 @@ class (or object)
report_builder, pvarray_parameters, timestamps, dni, dhi, \
solar_zenith, solar_azimuth, surface_tilt, surface_azimuth,\
albedo, cls_pvarray, cls_engine, cls_irradiance, cls_vf, \
fast_mode_pvrow_index, idx = args
fast_mode_pvrow_index, irradiance_model_params, idx = args

report = run_timeseries_engine(
report_builder.build, pvarray_parameters,
timestamps, dni, dhi, solar_zenith, solar_azimuth,
surface_tilt, surface_azimuth, albedo,
cls_pvarray=cls_pvarray, cls_engine=cls_engine,
cls_irradiance=cls_irradiance, cls_vf=cls_vf,
fast_mode_pvrow_index=fast_mode_pvrow_index)
fast_mode_pvrow_index=fast_mode_pvrow_index,
irradiance_model_params=irradiance_model_params)

return report, idx
55 changes: 39 additions & 16 deletions pvfactors/tests/test_run.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from pvfactors.run import run_timeseries_engine, run_parallel_engine
from pvfactors.report import ExampleReportBuilder
import numpy as np
import mock


def test_run_timeseries_engine(fn_report_example, params_serial,
Expand Down Expand Up @@ -36,9 +37,28 @@ def test_run_timeseries_engine(fn_report_example, params_serial,
8.642850754173368)


def test_run_parallel_engine(params_serial,
df_inputs_clearsky_8760):
def test_params_irradiance_model():
"""Test that irradiance params are passed correctly in
run_timeseries_engine"""
mock_irradiance_model = mock.MagicMock()
mock_engine = mock.MagicMock()
irradiance_params = {'horizon_band_angle': 15.}

_ = run_timeseries_engine(
None, None,
None, None, None, None, None, None,
None, None, cls_engine=mock_engine,
cls_irradiance=mock_irradiance_model,
irradiance_model_params=irradiance_params)

mock_irradiance_model.assert_called_once_with(
horizon_band_angle=irradiance_params['horizon_band_angle'])


def test_run_parallel_engine_with_irradiance_params(params_serial,
df_inputs_clearsky_8760):
"""Test that irradiance model params are passed correctly in parallel
simulations"""
df_inputs = df_inputs_clearsky_8760.iloc[:24, :]
n = df_inputs.shape[0]

Expand All @@ -50,22 +70,25 @@ def test_run_parallel_engine(params_serial,
solar_azimuth = df_inputs.solar_azimuth.values
surface_tilt = df_inputs.surface_tilt.values
surface_azimuth = df_inputs.surface_azimuth.values

n_processes = 2
report = run_parallel_engine(

irradiance_params = {'horizon_band_angle': 6.5}
report_no_params = run_parallel_engine(
ExampleReportBuilder, params_serial,
timestamps, dni, dhi, solar_zenith, solar_azimuth, surface_tilt,
surface_azimuth, params_serial['rho_ground'], n_processes=n_processes)
surface_azimuth, params_serial['rho_ground'], n_processes=n_processes,
irradiance_model_params=irradiance_params)

assert len(report['qinc_front']) == n
# Test value consistency: not sure exactly why value is not exactly equal
# to one in serial test, but difference not significant
np.testing.assert_almost_equal(np.nansum(report['qinc_back']),
np.testing.assert_almost_equal(np.nansum(report_no_params['qinc_back']),
541.7115807694377)
np.testing.assert_almost_equal(np.nansum(report['iso_back']),
18.050083142438311)
# Check that the reports were sorted correctly
np.testing.assert_almost_equal(report['qinc_back'][7],
11.160301350847325)
np.testing.assert_almost_equal(report['qinc_back'][-8],
8.642850754173368)

# The incident irradiance should be higher with larger horizon band
irradiance_params = {'horizon_band_angle': 15.}
report_w_params = run_parallel_engine(
ExampleReportBuilder, params_serial,
timestamps, dni, dhi, solar_zenith, solar_azimuth, surface_tilt,
surface_azimuth, params_serial['rho_ground'], n_processes=n_processes,
irradiance_model_params=irradiance_params)

np.testing.assert_almost_equal(np.nansum(report_w_params['qinc_back']),
554.5333279555168)
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
'Topic :: Scientific/Engineering',
]

TESTS_REQUIRES = ['pytest>=3.2.1', 'pytest-mock>=1.10.0']
TESTS_REQUIRES = ['pytest>=3.2.1', 'pytest-mock>=1.10.0', 'mock']

setup(name=DISTNAME,
description=DESCRIPTION,
Expand Down

0 comments on commit 1be5483

Please sign in to comment.