-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Clarify Egref and dEgdT values, changes calcparams_desoto api #471
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
Conversation
Fix total_irrad docstring
Fix formatting in irradiance.py
…to PVSystem.calcparams_desoto
…ts, remove M argument, change poa_irradiance to effective_irradiance, and add _build_kwargs to PVSystem.calcparams_desoto
…ts, remove M argument, change poa_irradiance to effective_irradiance, and add _build_kwargs to PVSystem.calcparams_desoto
Are the changes to the SAM file and irradiance.py due to some git hassles? If so, recommend
I'm not 100% sure, but I think this will remove the proposed changes to these files. |
def calcparams_desoto(effective_irradiance, temp_cell, | ||
alpha_sc, a_ref, I_L_ref, I_o_ref, R_sh_ref, R_s, | ||
EgRef=1.121, dEgdT=-0.0002677, | ||
irrad_ref=1000, temp_ref=25): |
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 think the desoto model is more naturally parameterized in terms of total irradiance at the POA. I propose that poa_global
be renamed to irrad_poa
, irrad_ref
be renamed to irrad_poa_ref
, and temp_ref
to temp_cell_ref
.
Also, calling this "effective irradiance" might be confused with the G_{eff} appearing in the DeSoto's master's thesis, which appears to have a different definition.
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.
@thunderfish24 here we have a conflict between adhering to the published reference (input would be absorbed irradiance, after reflections and soiling losses but without an adjustment from broadband to effective irradiance) and consistency within pvlib-python. SAPM (and PVsyst, when it is implemented #470) accept effective irradiance as input. I would prefer to see Desoto (and CEC, when it is implemented #463) use the same input quantity, with function signature and inline comments documenting the change from literature.
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.
From the standpoint of being able to implement and compare different models easily from the same time-dependent input data (say, global irradiance from pyranometer, albedo, ambient dry bulb temperature, and wind speed), I think having a consistent API would be preferable over complete fidelity to the original model formulation (and documenting the modifications in the code sounds acceptable). It sounds like the definition of "effective irradiance" that you are talking about here is the last one here with SF=1. Can you confirm?
I also realize that my thoughts are muddy on POA irradiance. In particular, the above-mentioned irradiance ratio at the POA doesn't seem to include any of the losses that give DeSoto's S or M factors (or an SF for that matter). It sounds like we plan on moving those factors into a separate function (or functions)?
Computation graphs might be helpful here for the various models taking inputs to outputs.
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.
SAPM documentation strikes again. The explanation of effective irradiance in SAPM is rather opaque and is the question we are asked most frequently. A better explanation would be:
- Ee is measured as a ratio of Isc to Isc at reference conditions adjusted for temperature (this is consistent with @thunderfish24 F quantity
- For prediction of power from broadband POA irradiance, Ee is calculated by reducing the POA by surface reflection, soiling and adjusting for spectrum. This calculation is implicit in Eq. 1 on this page : https://pvpmc.sandia.gov/modeling-steps/2-dc-module-iv/point-value-models/sandia-pv-array-performance-model/
I lost the argument to explicitly present SAPM along these lines on pvpmc.sandia.gov; the majority opinion was to retain the description as in the SAPM report.
From our attempts to bring order and consistency to PV modeling we arrived at this perspective:
- POA irradiance refers to broadband irradiance at the module's face. This is the quantity produced by all of the popular transposition models
- effective irradiance is the irradiance converted to electric current. Not everyone uses this term, but enough papers use it that we decided it made sense to emphasize it.
- translation of POA irradiance to effective irradiance accounts for reflections, soiling, spectral irradiance adjustment, and perhaps other mechanisms.
- De soto (and by inheritance CEC) is the only paper that uses a term for 'adsorbed irradiance', which is POA irradiance less reflections and soiling.
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.
Thanks for the further detailed explanation @cwhanse, which is making better sense to me now. I need a bit more time to think about the "swapping" of this effective irradiance into DeSoto, but it seems reasonable.
Also, it looks like the SAPM's effective irradiance does not try to treat the various angles of incidence of diffuse reflectance on the POA (which seems like a challenging prospect anyhow, and there is an f_D factor).
Note that the "effective irradiance" F in my definition here does not include a temperature correction to Isc0. This is not an approximation, but falls out of the derivation.
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.
One can derive an alternative auxiliary equation for the photocurrent I_L at operating conditions in the Desoto model by setting V=0 in the SDM and rearranging:
I_L = I_sc + I_D * (exp(I_sc * R_s / (N_S * n * V_th(T)) - 1) + I_sc * R_s / R_sh
= I_sc/I_sc_0 * I_sc_0 + I_D * (exp(I_sc/I_sc_0 * I_sc_0 * R_s / (N_S * n * V_th(T)) - 1) + I_sc/I_sc_0 * I_sc_0 * R_s / R_sh
= F * I_sc_0 + I_D * (F * I_sc_0 * R_s / (N_S * n * V_th(T)) - 1) + F * I_sc_0 * R_s / R_sh
where some of these other parameters are also computed at operating conditions (e.g., I_D).
One can then use equation (1) in the SAPM as the model for I_sc at operating conditions (possibly also with a SF) to compute F at operating conditions :).
I humbly request that we implement this auxiliary equation for I_L for the SDM in terms of F, which then would then allow us to use either the SAPM or a matched (or unmatched) PV reference device measurement for the determination of the control variable F.
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.
@thunderfish24 I could see your request being part of a new function calcparams_(name here). That would be consistent with the API: calcparams_xxxxx returns the 5 values for the single diode equation at irradiance and temperature, etc. My concerns are 1) a source of model parameters (the module-specific constants used by calcparams_xxxxx and 2) ensuring that users understand the input F. Most use cases start with measured broadband irradiance, although pvlib doesn't force the user to consider the instrument behind the measurement.
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.
K. I am happy to implement this after I work out a usage example with the SAPM I_sc in more detail. It seems to me that if someone is already using measured broadband irradiance as a starting point with SAPM, then that workflow should readily adapt to this implementation of SDM with existing calibration parameters (with only a translation of I_L0 to I_sc0, I think).
I also have to first wrap up #426. (I have most of the documentation done there except for some function parameter descriptions and two more tests that I really should write.)
@wholmgren yes the changes to the SAM file and irradiance.py are attempts to resolve git conflicts. The checkout/commit sequence you suggested fixed the issue. |
Ready to merge I think. |
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.
Mostly looks good.
These changes will break users' code. Do we want to go through the effort of a deprecation cycle? This would probably involve checking if the 4th argument (formerly module_parameters
) is a dict or Series, and, if so, dispatching the args/kwargs to an hidden implementation of the old function. The old function would emit a warning. It's not as straightforward as in #427, so maybe not worth the effort.
Inline comments below...
@@ -5,13 +5,14 @@ v0.6.0 (___, 2018) | |||
|
|||
API Changes | |||
~~~~~~~~~~~ | |||
|
|||
* pvsystem.calcparams_desoto now accepts only keyword arguments for each module model parameter. Prior to v0.6.0, pvsystem.calcparams_desoto required some module model parameters as keyword argument and accpted a dict, module_parameters, as an input providing the remaining module model parameters. |
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.
Recommend something more like:
pvsystem.calcparams_desoto now requires arguments for each module model parameter.
The arguments you've added are positional, not keyword-only.
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.
The whatsnew files generally use an 80 character line limit, though this is not as strict as for python modules.
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.
accpted --> accepted
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.
shortened to pvsystem.calcparams_desoto now requires arguments for each module model parameter.
to stay within character limits.
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.
Ok. To be clear and for future reference, you can also continue on to additional lines if you indent them by 2 spaces so that it looks like
* this is a long item....
that continues here...
pvlib/pvsystem.py
Outdated
temperature). | ||
temperature). For parameters read from | ||
the SAM CEC module database, dEgdT=-0.0002677 is imposed by the | ||
parameter estimation algorithm used by NREL. |
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.
remove M
documentation below here.
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.
done
pvlib/pvsystem.py
Outdated
# Note that the equation for Rsh differs from [1]. In [1] Rsh is given as | ||
# Rsh = Rsh_ref * (S_ref / S) where S is broadband irradiance reaching | ||
# the module's cells. If desired this model behavior can be duplicated | ||
# by applying reflection and soiing losses to broadband plane of array |
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.
soiing --> soiling
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.
fixed
def calcparams_desoto(poa_global, temp_cell, alpha_isc, module_parameters, | ||
EgRef, dEgdT, M=1, irrad_ref=1000, temp_ref=25): | ||
def calcparams_desoto(effective_irradiance, temp_cell, | ||
alpha_sc, a_ref, I_L_ref, I_o_ref, R_sh_ref, R_s, |
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 will repeat my preference for spelling out most of these arguments in the function signature as in i_from_v. It would require adding some mapping function within PVSystem.calcparams_desoto
but I think that's worth it for more descriptive argument names. The descriptive parameter names could be reassigned to the short names to keep the equations more readable.
The abbreviated names are still an improvement to the existing API, so I do not object to moving forward as is after some consideration.
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 agree with your preference but I'd like to defer it to a pull request with a larger scope. The short argument names, e.g., alpha_sc
, R_sh_ref
, R_s
(notice the discrepancy) are inherited from the column headings in the SAM database file. We read the column headings from the SAM file, do some character replacement, then use the reformatted names as keys.
Using long names in calcparams_desoto
would ripple to edits to pvsystem.retrieve_sam
, where the long names would be assigned as keys, in order to maintain the functionality of _build_kwargs
. I considered doing this but decided it was outside the scope of #462, the issue motivating this pull request.
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.
Works for me.
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.
The R_s instead of R_s_ref in SAM has always puzzled me.
…rguments detected
@wholmgren thanks for the careful checking and proofreading. I have added a less-clumsy exit from calcparams_desoto if the 4th positional argument looks like the old |
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 don't know if we really need to bother with a test for the new code path, but did you confirm that it works?
pvlib/pvsystem.py
Outdated
@@ -1133,6 +1121,28 @@ def calcparams_desoto(effective_irradiance, temp_cell, | |||
Source: [4] | |||
''' | |||
|
|||
# test for use of function pre-v0.6.0 API change | |||
if isinstance(a_ref, dict) or \ | |||
(isinstance(a_ref, pd.Series) and ('a_ref' in a_ref.keys())): |
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 don't understand the grouping of statements here. I would have thought you'd group on the or
rather than the and
. In any case, I think isinstance(a_ref, (dict, pd.Series))
alone may be what we want. A dict or Series that does not have 'a_ref' will fail in the equations that follow. Better to have it fail in the key look up. But maybe I am just misunderstanding.
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.
Tested the if
block on my own.
I added that block because I am assuming a use case where multiple sets of module parameters are passed into the new function as pandas.Series
objects, and I didn't want the new function to fail in that case.
if isinstance(a_ref, dict) or \ | ||
(isinstance(a_ref, pd.Series) and ('a_ref' in a_ref.keys())): | ||
import warnings | ||
warnings.warn('module_parameters detected as fourth positional' |
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.
Recommend using warnings.warn(message, DeprecationWarning)
where message is both of your statements as one.
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.
Done
pvlib/pvsystem.py
Outdated
I_o_ref = module_parameters['I_o_ref'] | ||
R_sh_ref = module_parameters['R_sh_ref'] | ||
R_s = module_parameters['R_s'] | ||
warnings.warn('module parameters extracted from fourth positional'\ |
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.
No need for this warning. We already told them once above. Safe to assume success unless exception raised below.
pvlib/pvsystem.py
Outdated
R_s = module_parameters['R_s'] | ||
warnings.warn('module parameters extracted from fourth positional'\ | ||
+ ' argument') | ||
except: |
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.
Recommend something like
except Exception as e:
raise e('Module parameters could not be extracted from '
'4th positional argument. Check that parameters are '
'from CEC database and/or update your code for new API.')
and then no need for the warning or return below
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.
OK
I think this is ready to go. Does anyone object? |
Is there a way to rerun the test? Looks like an unrelated failure in forecast.py |
We used to close and reopen PR at my last job, but that was for a different build system. |
@wholmgren or any pvlib admin, can do it from the pvlib Travis ci page there's usually a button that says rebuild. You can also use the Travis API but looks like this build already passed? |
under reference conditions. | ||
* R_sh_ref - shunt resistance under reference conditions (ohms). | ||
* R_s - series resistance under reference conditions (ohms). | ||
module in units of A/C. |
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.
C could be confused with Coulombs. Perhaps degC is preferable. (This is also an issue in temp_cell above.)
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 think the unit is clear in the context of the docstring.
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.
Amps/Coulomb = 1/second
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'd like to leave the temperature unit on the temperature coefficients as C, because that's the unit used in IEC standards and datasheets. I agree with @wholmgren about being clear in context.
pvlib/pvsystem.py
Outdated
The energy bandgap at reference temperature (in eV). | ||
1.121 eV for silicon. EgRef must be >0. | ||
The energy bandgap at reference temperature in units of eV. | ||
1.121 eV for silicon. EgRef must be >0. For parameters read from |
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.
nit: Might it be better to say crystalline Silicon here (as opposed to amorphous, etc.)?
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.
Good point, 1.121eV is for crystalline silicon.
pvlib/pvsystem.py
Outdated
The temperature dependence of the energy bandgap at SRC (in | ||
1/C). May be either a scalar value (e.g. -0.0002677 as in [1]) | ||
The temperature dependence of the energy bandgap at reference | ||
conditions in units of 1/C. May be either a scalar value (e.g. -0.0002677 as in [1]) |
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.
C could be confused with Coulombs. Perhaps degC is preferable.
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 changed this one to 1/K, because we use Kelvin in the calculation.
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 had some minor suggestions. I noticed some notebook cell execution failures in the desoto
section of docs/tutorials/pvsystem.ipynb
. Perhaps that notebook needs updating?
pvlib/pvsystem.py
Outdated
Tref_K = temp_ref + 273.15 | ||
Tcell_K = temp_cell + 273.15 | ||
|
||
E_g = EgRef * (1 + dEgdT*(Tcell_K - Tref_K)) | ||
|
||
nNsVth = a_ref * (Tcell_K / Tref_K) | ||
|
||
IL = (poa_global/irrad_ref) * M * (IL_ref + alpha_isc * (Tcell_K - Tref_K)) | ||
I0 = (I0_ref * ((Tcell_K / Tref_K) ** 3) * | ||
IL = effective_irradiance / irrad_ref * \ |
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.
Perhaps a comment here on how this differs from the DeSoto model's uses of S, M, etc.?
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.
Added
I restarted the Appveyor build. I don't know if that requires admin access or not. |
I updated the notebook |
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.
Thanks for considering my suggestions.
I ran the pvsystem.ipynb tutorial. It looks good to me. Results here. The PR currently contains output with exceptions, but that is ok with me. If you do want to clean it up... I run notebooks against test code using the procedure outlined here. It's simplest if you start the jupyter notebook server within the virtual environment you've created for pvlib development rather than using the jupyter notebook server that came with your base Anaconda installation (assuming that's what you're using). Again, ok with me if we skip it for now. Thanks @thunderfish24 for your careful reviews. |
pvlib python pull request guidelines
Thank you for your contribution to pvlib python!
You may submit a pull request with your code at any stage of completion, however, before the code can be merged the following items must be addressed:
git diff upstream/master -u -- "*.py" | flake8 --diff
and/or landscape.io linting service.docs/sphinx/source/api.rst
for API changes.docs/sphinx/source/whatsnew
file for all changes.Please don't hesitate to ask for help if you're unsure of how to accomplish any of the above. You may delete all of these instructions except for the list above.
Brief description of the problem and proposed solution (if not already fully described in the issue linked to above):
Sets default values for CEC module parameters
Egref
anddEgdT
inpvsystem.calcparams_desoto
. Changes API forpvsystem.calcparams_desoto
to individual keyword arguments, removing themodule_parameters
dict). Adds_build_kwargs
toPVSystem.calcparams_desoto
I believe this is ready to merge. I could not fully check out the changes in the tutorial file, since the Jupyter notebook is calling
calcparams_desoto