-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Expose first_solar_spectral_correction #466
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 10 commits
ffd685c
0881f01
6d47188
7a04b02
88fe65e
2da94e3
210e813
dec5d95
0732b4c
ce78670
e8de2e0
bd7e119
19de627
67a4561
e4724ae
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 |
|---|---|---|
|
|
@@ -421,6 +421,87 @@ def sapm_effective_irradiance(self, poa_direct, poa_diffuse, | |
| poa_direct, poa_diffuse, airmass_absolute, aoi, | ||
| self.module_parameters, reference_irradiance=reference_irradiance) | ||
|
|
||
| def first_solar_spectral_loss(self, pw, airmass_absolute): | ||
|
|
||
| """ | ||
| Use the :py:func:`first_solar_spectral_correction` function to | ||
| calculate the spectral loss modifier. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| pw : array-like | ||
| atmospheric precipitable water (cm). | ||
|
|
||
| airmass_absolute : array-like | ||
| absolute (pressure corrected) airmass. | ||
|
|
||
| Returns | ||
| ------- | ||
| modifier: array-like | ||
| spectral mismatch factor (unitless) which can be multiplied | ||
| with broadband irradiance reaching a module's cells to estimate | ||
| effective irradiance, i.e., the irradiance that is converted to | ||
| electrical current. | ||
| """ | ||
|
|
||
| if 'first_solar_spectral_coefficients' in self.module_parameters.keys(): | ||
| coefficients = \ | ||
| self.module_parameters['first_solar_spectral_coefficients'] | ||
| module_type = None | ||
| else: | ||
| module_type = self._infer_cell_type() | ||
|
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. module vs. cell is unfortunate here. No objection to what you've done, but we might need a separate discussion to try to clean up the terminology within the library.
Member
Author
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. Here I'm inclined to break the API and change the keyword argument from module_type to cell_type. module_type is only used by the first_solar function. |
||
| coefficients = None | ||
|
|
||
| return atmosphere.first_solar_spectral_correction(pw, | ||
| airmass_absolute, | ||
| module_type, | ||
| coefficients) | ||
|
|
||
| def _infer_cell_type(self): | ||
|
|
||
| """ | ||
| Examines module_parameters and maps the Technology key for the CEC | ||
| database and the Material key for the Sandia database to a common | ||
| list of strings for cell type. | ||
|
|
||
| Returns | ||
| ------- | ||
| cell_type: str | ||
|
|
||
| """ | ||
|
|
||
| _cell_type_dict = {'Multi-c-Si': 'multisi', | ||
| 'Mono-c-Si': 'monosi', | ||
| 'Thin Film': 'cigs', | ||
| 'a-Si/nc': 'asi', | ||
| 'CIS': 'cigs', | ||
| 'CIGS': 'cigs', | ||
| '1-a-Si': 'asi', | ||
| 'CdTe': 'cdte', | ||
| 'a-Si': 'asi', | ||
| '2-a-Si': None, | ||
| '3-a-Si': None, | ||
| 'HIT-Si': 'monosi', | ||
| 'mc-Si': 'multisi', | ||
| 'c-Si': 'multisi', | ||
| 'Si-Film': 'asi', | ||
| 'CdTe': 'cdte', | ||
| 'EFG mc-Si': 'multisi', | ||
| 'GaAs': None, | ||
| 'a-Si / mono-Si': 'monosi'} | ||
|
|
||
| if 'Technology' in self.module_parameters.keys(): | ||
| # CEC module parameter set | ||
| cell_type = _cell_type_dict[self.module_parameters['Technology']] | ||
| elif 'Material' in self.module_parameters.keys(): | ||
| # Sandia module parameter set | ||
| cell_type = _cell_type_dict[self.module_parameters['Material']] | ||
| else: | ||
| cell_type = None | ||
|
|
||
| return cell_type | ||
|
|
||
|
|
||
| def singlediode(self, photocurrent, saturation_current, | ||
| resistance_series, resistance_shunt, nNsVth, | ||
| ivcurve_pnts=None): | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -263,21 +263,16 @@ def constant_spectral_loss(mc): | |
| mc.spectral_modifier = 0.9 | ||
|
|
||
| @requires_scipy | ||
| @pytest.mark.parametrize('spectral_model, expected', [ | ||
| ('sapm', [182.338436597, -2.00000000e-02]), | ||
| pytest.mark.xfail(raises=NotImplementedError) | ||
| (('first_solar', [179.371460714, -2.00000000e-02])), | ||
| ('no_loss', [181.604438144, -2.00000000e-02]), | ||
| (constant_spectral_loss, [163.061569511, -2e-2]) | ||
| ]) | ||
| def test_spectral_models(system, location, spectral_model, expected): | ||
| @pytest.mark.parametrize('spectral_model', ['sapm', 'first_solar', 'no_loss']) | ||
|
||
|
|
||
| def test_spectral_models(system, location, spectral_model): | ||
| times = pd.date_range('20160101 1200-0700', periods=3, freq='6H') | ||
| weather = pd.DataFrame(data=[0.3, 0.5, 1.0], index=times, columns=['precipitable_water']) | ||
| mc = ModelChain(system, location, dc_model='sapm', | ||
| aoi_model='no_loss', spectral_model=spectral_model) | ||
| times = pd.date_range('20160101 1200-0700', periods=2, freq='6H') | ||
| ac = mc.run_model(times).ac | ||
|
|
||
| expected = pd.Series(np.array(expected), index=times) | ||
| assert_series_equal(ac, expected, check_less_precise=2) | ||
| spectral_modifier = mc.run_model(times=times, weather=weather).spectral_modifier | ||
| print(spectral_modifier) | ||
|
||
| assert isinstance(spectral_modifier, (pd.Series, float, int)) | ||
|
|
||
|
|
||
| def constant_losses(mc): | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -266,6 +266,17 @@ def test_PVSystem_sapm_spectral_loss(sapm_module_params): | |
| out = system.sapm_spectral_loss(airmass) | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("expected", [1.03173953]) | ||
|
|
||
|
||
| def test_PVSystem_first_solar_spectral_loss(sapm_module_params, expected): | ||
| system = pvsystem.PVSystem(module_parameters=sapm_module_params) | ||
| pw = 3 | ||
| airmass_absolute = 3 | ||
| out = system.first_solar_spectral_loss(pw, airmass_absolute) | ||
|
|
||
| assert_allclose(out, expected, atol=1e-4) | ||
|
|
||
|
|
||
| @pytest.mark.parametrize('aoi,expected', [ | ||
| (45, 0.9975036250000002), | ||
| (np.array([[-30, 30, 100, np.nan]]), | ||
|
|
||
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.
Doc string should have some kind of reference to
self.module_parameters. Most of the otherPVSystemmethod doc strings have some examples. This method is a little more complicated though, so might be worth being more explicit about what is looked for. For example...Use the :py:func:
first_solar_spectral_correctionfunction to calculate the spectral loss modifier. The spectral loss modifier is determined by searching for one of the following keys inself.module_parameters(in order):'first_solar_spectral_coefficients','Technology','Material'.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.