-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Make interp IAM method available for modelchain #1832
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 all commits
ce2fb60
f562c28
ac7af3c
fc996ea
8febd15
9cc8e68
c5e0556
b079512
efe35ee
458dbce
3db5704
f544ba4
510947c
4054c66
da87b9f
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 |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
import io | ||
import itertools | ||
import os | ||
import inspect | ||
from urllib.request import urlopen | ||
import numpy as np | ||
from scipy import constants | ||
|
@@ -388,7 +389,7 @@ def get_iam(self, aoi, iam_model='physical'): | |
|
||
aoi_model : string, default 'physical' | ||
The IAM model to be used. Valid strings are 'physical', 'ashrae', | ||
'martin_ruiz' and 'sapm'. | ||
'martin_ruiz', 'sapm' and 'interp'. | ||
Returns | ||
------- | ||
iam : numeric or tuple of numeric | ||
|
@@ -1151,7 +1152,7 @@ def get_iam(self, aoi, iam_model='physical'): | |
|
||
aoi_model : string, default 'physical' | ||
The IAM model to be used. Valid strings are 'physical', 'ashrae', | ||
'martin_ruiz' and 'sapm'. | ||
'martin_ruiz', 'sapm' and 'interp'. | ||
|
||
Returns | ||
------- | ||
|
@@ -1164,16 +1165,16 @@ def get_iam(self, aoi, iam_model='physical'): | |
if `iam_model` is not a valid model name. | ||
""" | ||
model = iam_model.lower() | ||
if model in ['ashrae', 'physical', 'martin_ruiz']: | ||
param_names = iam._IAM_MODEL_PARAMS[model] | ||
kwargs = _build_kwargs(param_names, self.module_parameters) | ||
func = getattr(iam, model) | ||
if model in ['ashrae', 'physical', 'martin_ruiz', 'interp']: | ||
func = getattr(iam, model) # get function at pvlib.iam | ||
# get all parameters from function signature to retrieve them from | ||
# module_parameters if present | ||
params = set(inspect.signature(func).parameters.keys()) | ||
params.discard('aoi') # exclude aoi so it can't be repeated | ||
kwargs = _build_kwargs(params, self.module_parameters) | ||
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. Makes me wonder if the IAM parameters should have been tracked in their own separate data structure instead of having to be extracted from 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. I think they only reason they were in |
||
return func(aoi, **kwargs) | ||
elif model == 'sapm': | ||
return iam.sapm(aoi, self.module_parameters) | ||
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. I notice also that we don't have a way to pass 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. Hmmmm. I don't like many things about the current interface of these IAM functions; IMO, a good approach is shown at def physical(aoi, n=1.526, K=4.0, L=0.002, *, n_ar=None): Note the asterisk (it means following args are keyword-only args just in case). Each argument, of different kinds, parse to a real-world meaning (again, IMO).
I would still upgrade the function signature to: def physical(aoi, /, n=1.526, K=4.0, L=0.002, *, n_ar=None): So it is always the first parameter the input. This is completely unnecessary in IAM models since the only required input to work is Why this proposal?Because of the inspect module. In this PR I used it to retrieve all the parameters needed: if model in ['ashrae', 'physical', 'martin_ruiz', 'interp']:
func = getattr(iam, model) # get function at pvlib.iam
# get all parameters from function signature to retrieve them from
# module_parameters if present
params = set(inspect.signature(func).parameters.keys())
params.discard('aoi') # exclude aoi so it can't be repeated
kwargs = _build_kwargs(params, self.module_parameters)
return func(aoi, **kwargs) With this broad approach to the function parameter meanings, we could test for the types of each one and infer it's use with I tried not to use In short,I propose a normalized way of defining function signatures, where:
[1] Since also required ones are those without default values and it can also be checked with the inspect module. In the case of IAM module: def ashrae(aoi, /, b=0.05):
def physical(aoi, /, n=1.526, K=4.0, L=0.002, *, n_ar=None):
def martin_ruiz(aoi, /, a_r=0.16):
def martin_ruiz_diffuse(surface_tilt, /, a_r=0.16, c1=0.4244, *, c2=None):
def interp(aoi, theta_ref, iam_ref, *, method='linear', normalize=True):
def sapm(aoi, /, module, *, upper=None): # here module should be changed to B5 ... B0
... Or without the I see this got really long, may I open a discussion? 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.
Absolutely! Better to have a dedicated thread for this. Otherwise it will get buried soon when the PR is merged :) |
||
elif model == 'interp': | ||
raise ValueError(model + ' is not implemented as an IAM model ' | ||
'option for Array') | ||
else: | ||
raise ValueError(model + ' is not a valid IAM model') | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.