Skip to content

add mlfm #1354

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

Open
wants to merge 94 commits into
base: main
Choose a base branch
from
Open

add mlfm #1354

wants to merge 94 commits into from

Conversation

steve-ransome
Copy link

@steve-ransome steve-ransome commented Dec 10, 2021

@steve-ransome
Copy link
Author

This is the MLFM paper as submitted (without the header)
2209_MLFM_WCPEC8_Ransome_3BV.3.14_pvlib.pdf

Copy link
Contributor

@markcampanelli markcampanelli left a comment

Choose a reason for hiding this comment

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

@steve-ransome Thanks for this submission.

Here is my review of your core algorithm, esp. the normalization and fitting. I have not yet run any examples or looked at the error stacking, plotting functions, or tests.

The main issue I see is potentially more careful handling of the fits in the special case where no windspeed info is provided. I think this should be investigated a bit further and would be happy to discuss.

try:
import matplotlib.pyplot as plt # noqa: F401
import matplotlib
matplotlib.use('agg')
Copy link
Contributor

@markcampanelli markcampanelli Oct 13, 2022

Choose a reason for hiding this comment

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

Configure the agg backend first before importing anything else from matplotlib?

Given the import matplotlib, is import matplotlib.pyplot as plt even necessary here?

pvlib/mlfm.py Outdated
T_STC = 25.0 # STC temperature [C] temperature_ref
T_HTC = 75.0 # HTC temperature [C]
G_STC = 1000.0 # STC irradiance [W/m^2]
G_LIC = 0.2 # LIC irradiance [kW/m^2]
Copy link
Contributor

Choose a reason for hiding this comment

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

It's a bit unexpected to change the units between G_STC and G_LIC, even though it is documented.

Also, is G_LIC actually used?

Copy link
Author

Choose a reason for hiding this comment

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

They should be the same units, one was changed without the other. G_LIC hasn't been used here but will be used in later code changes as the MLFM can create useful performance values at other conditions such as LIC, HTC, NOCT etc. for validation.

Copy link
Contributor

Choose a reason for hiding this comment

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

For completeness and explicitness, you could include G_HTC, and T_LIC, as well as the G_LTC and T_LTC (and perhaps G_NOCT) conditions defined in IEC 61853-1.

Copy link
Author

Choose a reason for hiding this comment

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

NAME value # comment unit PV_LIB name

T_STC = 25.0 # STC temperature [C] temperature_ref
G_STC = 1000.0 # STC irradiance [W/m^2]

not all yet used below , added here for completeness

T_LIC = 25.0 # LIC temperature [C]
G_LIC = 200.0 # LIC irradiance [W/m^2]

T_HTC = 75.0 # HTC temperature [C]
G_HTC = 1000.0 # HTC irradiance [W/m^2]

T_PTC = 55.0 # HTC temperature [C]
G_PTC = 1000.0 # HTC irradiance [W/m^2]

G_LTC = 500.0 # HTC irradiance [W/m^2]
T_LTC = 15.0 # LTC temperature [C]

G_NOCT = 800 # NOCT irradiance [W/m^2]
T_NOCT = 45 # NOCT temperature [C]

Copy link
Author

Choose a reason for hiding this comment

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

Note that some of these such as T_NOCT depend on the module type so I have added an example value of 45.
T_PTC is also a ballpark figure as it is taken at T_amb=20 and has to assume a noct.
T_ptc ~ 20 + 1000/800 * (Noct -20) ~ 50C

https://sinovoltaics.com/learning-center/quality/ptc-pv-usa-test-conditions/

pvlib/mlfm.py Outdated

Parameters
----------
data : DataFrame
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be too verbose to include typical values for var_to_fit in the docstring for that argument?

pvlib/mlfm.py Outdated
c5_zero = 'wind_speed' not in data.columns
# if wind_speed is not present, add it
if c5_zero:
data['wind_speed'] = 0.
Copy link
Contributor

@markcampanelli markcampanelli Oct 13, 2022

Choose a reason for hiding this comment

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

Technically, c5 is unidentifiable if the data do not contain windspeed information. As such, the algorithm may not converge robustly and may report convergence problems when you nonetheless keep c5 in the model. (Your bounds on c5 may temper the convergence issues to some degree.)

Unfortunately, scipy.optimize.curve_fit does not allow you to specify equal upper and lower bounds for c5 in this case, which here is presumably zero by convention. I can suggest a couple ways to work around this, but first I suggest examining the convergence info from scipy.optimize.curve_fit in a case where there is no windspeed info. (Do this by passing full_output=True and examining the additional mesg and ierint outputs.)

Copy link
Contributor

Choose a reason for hiding this comment

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

I made comparison curve_fits using datasets n05667_Y13_R1k6_fClear_041.csv and x19074001_iec61853_041.csv, both of which have no wind_speed info. For the comparison, I removed the c5 coefficient altogether from mlfm_6 (instead using a new mlfm_5 function for func). The remaining coefficients appear to be stable between the two approaches without convergence errors in either (although the convergence criterion may change from gtol to ftol). I did not check the results of of the fit beyond this. It appears that it is ok to use mlfm_6 in all cases, but I would still recommend checking for convergence.

pvlib/mlfm.py Outdated
coeff_err = list(perr)

# save fit and error to dataframe
pred = mlfm_6(data, coeff[0], coeff[1], coeff[2], coeff[3], coeff[4],
Copy link
Contributor

Choose a reason for hiding this comment

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

I think that you can pass full_output=True to scipy.optimize.curve_fit, then get the pred variable pre-calculated as infodict["fvec"] from the additional output infodict from scipy.optimize.curve_fit.

full_output=True also provides two more outputs: mesg and ierint, which you should inspect for convergence information, possibly warning the user and/or passing back to the caller.

https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html

@@ -150,6 +150,17 @@ def has_numba():
requires_siphon = pytest.mark.skipif(not has_siphon,
reason='requires siphon')

try:
import matplotlib.pyplot as plt # noqa: F401
Copy link
Contributor

@markcampanelli markcampanelli Oct 13, 2022

Choose a reason for hiding this comment

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

Why is this import made here, since import matplotlib is made next?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm 99% sure that the import matplotlib.pyplot as plt is not needed.

@markcampanelli
Copy link
Contributor

Because there are several mflm-related tutorial notebooks and supporting files, we may want to add a general docs/tutorials/mflm/ directory (with a data sub-directory) to hold everything.

@steve-ransome
Copy link
Author

steve-ransome commented Oct 17, 2022

We already do that. , there are directories for reference data, meas_gtw measurements+weather, figs and outputs

@markcampanelli
Copy link
Contributor

We already do that. , there are directories for reference data, meas_gtw measurements+weather, figs and outputs

I may have not been clear. I was thinking in terms of how this structure might better grow and coexist with other multi-file tutorials.

mflm alternative directory structure

@markcampanelli
Copy link
Contributor

markcampanelli commented Nov 14, 2022

@steve-ransome In the example notebooks, don't use Windows-specific path separators, which don't work on Mac/Linux. For example, instead of
ref_file_name = (root_dir + '\\mlfm_data\\ref\\' + 'mlfm_reference_modules.csv'),
use
ref_file_name = os.path.join(root_dir, 'mlfm_data', 'ref', 'mlfm_reference_modules.csv')

@steve-ransome
Copy link
Author

Thanks, have updated mlfm to use that

@markcampanelli
Copy link
Contributor

@steve-ransome Would it be helpful at this point for me to review all the comments that I initiated and resolve/follow up with them?

@steve-ransome
Copy link
Author

Thanks @markcampanelli that would be very useful. I think I've got as far as I can for the moment.

@markcampanelli
Copy link
Contributor

@steve-ransome I walked through the comment history, and there seems to be some unresolved ones from all the reviewers (including me). Not sure if the maintainers are open to arranging a conference call to walk through all of these?

Personally I have few outstanding small issues, whereas my main issue is that the coefficient-solver information is not propagated back to the user, including a potential convergence failure.

In particular, I think the whatsnew info is still missing. This depends on the intended release version, and I wonder if the MLFM addition warrants a "new feature" version bump to v0.10.0, which would likely queue it behind the pending v0.9.4 release.

@adriesse
Copy link
Member

adriesse commented Dec 5, 2022

Personally I have few outstanding small issues, whereas my main issue is that the coefficient-solver information is not propagated back to the user, including a potential convergence failure.

This could be a more general question about how we would like fitting functions in pvlib to behave. curve_fit will raise a warning or exception if things go terribly wrong. Is that suitable and/or sufficient? Admittedly the user will have to have a higher level of expertise to figure out what might be the problem. If this is not good enough, then maybe we shouldn't be using curve_fit but rather some lower level function like least_squares or minimize.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Adding the Loss Factors Model and Mechanistic Performance Models to PVLIB
7 participants