-
Notifications
You must be signed in to change notification settings - Fork 1.1k
WIP: Speed up singlediode._lambertw #1661
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
base: main
Are you sure you want to change the base?
Conversation
Coverage drops because I have not (yet) removed the now-unused private function which was maximized to find the MPP with the golden mean search. Assuming this PR is approved, that helper function can be removed before merging. |
@pvlib/pvlib-maintainer I can't get the environment to solve to run the benchmark. Is it simple for one of you to run the new benchmark and suggest any edits/corrections? |
If you're referring to the conda environment, have you tried Mambaforge? Mamba is an improved solver that replaces conda. It usually solves environments faster and with less clashes in difficult environments. I have been using it for a little over a year, and IME it is a significant improvement over conda. If you prefer, you can just install mamba in your base miniconda/anaconda environment by using |
Just looking at the CI, the |
I can rewind to numpy 1.16, it shouldn't affect the time for the benchmarks. |
I can't find where that error was happening - the CI report for the asv action looks green to me. Did you run that locally (whcih I haven't been able to do), or where should I be looking? It doesn't appear that this new benchmark is being run yet. |
I almost never run the benchmarks locally. I vaguely recall having problems getting them working on Windows. I'm pretty sure I've run them locally on Linux before. The nightly benchmark server runs some flavor of Linux. Here's the ASV run for 063abf8 which has the error I mentioned: https://github.com/pvlib/pvlib-python/actions/runs/4168577294/jobs/7215540457 I guess the job is (mis)configured in such a way that python errors in the benchmarks don't propagate out to become a CI job failure, so we always get the green checkmark here on the PR. That needs to be fixed.
I think asv identifies benchmarks by looking for functions/methods whose name begins with |
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.
Haven't inspected the math yet
Co-authored-by: Kevin Anderson <[email protected]>
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 have now worked through (most of) the math myself.
Shall we delete _golden_sect_DataFrame
and _pwr_optfcn
if they aren't used anywhere anymore?
Also can we change the URLs for reference 3 in user_guide/singlediode.rst
? One of them seems to be behind a Sandia login page and the other is Research Gate. Better alternatives:
args=args) | ||
v_mp = _lambertw_v_from_i(resistance_shunt, resistance_series, nNsVth, | ||
i_mp, saturation_current, photocurrent) | ||
p_mp = i_mp * v_mp | ||
|
||
# Find Imp using Lambert W | ||
i_mp = _lambertw_i_from_v(resistance_shunt, resistance_series, nNsVth, |
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 this i_mp
calculation is now redundant and can be nixed.
if np.any(idx_z): | ||
# explicit solution for gsh=0 | ||
t = il[idx_z] + io[idx_z] - i[idx_z] | ||
res[idx_z] = i[idx_z] / t - np.log(t / io[idx_z]) |
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.
When I derive this by hand I get an extra 2*i*rs/a
term. Am I making a mistake? With the goal of finding a root of
In the limit
This can be rearranged to solve explicitly for
Differentiating
Hence:
The derivative is zero at
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.
You're correct, I dropped a sign change.
(gsh * a))) | ||
lambertwterm = np.array(lambertw(argW).real) | ||
|
||
idx_inf = np.logical_not(np.isfinite(lambertwterm)) |
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.
This will cause both nan
and inf
to be recalculated, which I'm guessing isn't desirable if the goal is to only recalculate for inf
if np.any(idx_z): | ||
# explicit solution for gsh=0 | ||
t = il[idx_z] + io[idx_z] - i[idx_z] | ||
res[idx_z] = 2. / t + i[idx_z] / t**2. |
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.
Depending on whether my previous comment regarding a missing term is in error, this may also need an additional term
I vote 'yes' |
Moving this back to WIP, because I'm finding convergence problems with corner cases: Rsh=infinity, IL=0. Back to paper and pen. |
[ ] Updates entries indocs/sphinx/source/reference
for API changes.docs/sphinx/source/whatsnew
for all changes. Includes link to the GitHub Issue with:issue:`num`
or this Pull Request with:pull:`num`
. Includes contributor name and/or GitHub username (link with:ghuser:`user`
).remote-data
) and Milestone are assigned to the Pull Request and linked Issue.Implements and documents the solution technique illustrate in this gist for solving for the maximum power point using the Lambert W method.