Skip to content

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

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

Conversation

cwhanse
Copy link
Member

@cwhanse cwhanse commented Feb 13, 2023

  • Closes Accelerate singlediode._lambertw #1649
  • I am familiar with the contributing guidelines
  • Tests added
  • [ ] Updates entries in docs/sphinx/source/reference for API changes.
  • Adds description and name entries in the appropriate "what's new" file in 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`).
  • New code is fully documented. Includes numpydoc compliant docstrings, examples, and comments where necessary.
  • Pull request is nearly complete and ready for detailed review.
  • Maintainer: Appropriate GitHub Labels (including 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.

@cwhanse
Copy link
Member Author

cwhanse commented Feb 13, 2023

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.

@cwhanse
Copy link
Member Author

cwhanse commented Feb 14, 2023

@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?

@cwhanse cwhanse changed the title WIP: speed up singlediode._lambertw Speed up singlediode._lambertw Feb 14, 2023
@mikofski
Copy link
Member

I can't get the environment to solve to run the benchmark

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 conda install -c conda-forge mamba rather switching to Mambaforge. Or if you have the latest conda, there is an experimental option to use libmamba since conda-4.12, but it is an older version, I found the experience poor, and inconsistent compared with the version of mamba from conda-forge.

@kandersolar
Copy link
Member

Just looking at the CI, the quick-benchmarks jobs is erroring with ImportError: cannot import name 'Generator' from 'numpy.random' with numpy=1.16.5. It looks like Generator was added in numpy 1.17.0, so I guess we'll need to either bump the numpy version in the ASV configuration, or not use Generator in the benchmarks. Either way is fine with me.

@cwhanse
Copy link
Member Author

cwhanse commented Feb 14, 2023

I can rewind to numpy 1.16, it shouldn't affect the time for the benchmarks.

@cwhanse
Copy link
Member Author

cwhanse commented Feb 14, 2023

Just looking at the CI, the quick-benchmarks jobs is erroring with ImportError: cannot import name 'Generator' from 'numpy.random' with numpy=1.16.5. It looks like Generator was added in numpy 1.17.0, so I guess we'll need to either bump the numpy version in the ASV configuration, or not use Generator in the benchmarks. Either way is fine with me.

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.

@kandersolar
Copy link
Member

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.

It doesn't appear that this new benchmark is being run yet.

I think asv identifies benchmarks by looking for functions/methods whose name begins with time_, so renaming the benchmarks from bishop88 -> time_bishop88 should get it working.

Copy link
Member

@kandersolar kandersolar left a 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

Copy link
Member

@kandersolar kandersolar left a 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,
Copy link
Member

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])
Copy link
Member

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 $\frac{dP}{dI}=V + I \frac{dV}{dI}$, start with the single diode equation:

$$ I = I_L - I_0 \left(\exp \left(\frac{V + I R_s}{n Ns V_{th}} \right) - 1 \right) - \frac{V + I R_s}{R_{sh}} $$

In the limit $R_{sh}\rightarrow\infty$, the last term vanishes:

$$ I = I_L - I_0 \left(\exp \left(\frac{V + I R_s}{n Ns V_{th}} \right) - 1 \right) $$

This can be rearranged to solve explicitly for $V$:

$$ V = n Ns V_{th} \log \left(\frac{I_L + I_0 - I}{I_0}\right) - I R_s $$

Differentiating $V$ with respect to $I$ yields

$$ \frac{dV}{dI} = - \frac{n Ns V_{th}}{I_L + I_0 - I} - R_s $$

Hence:

$$ \frac{dP}{dI} = n Ns V_{th} \log \left(\frac{I_L + I_0 - I}{I_0}\right) - I \frac{n Ns V_{th}}{I_L + I_0 - I} - 2 I R_s $$

The derivative is zero at $I_{mp}$, thus:

$$ \log \left(\frac{I_L + I_0 - I_{mp}}{I_0}\right) - \frac{I_{mp}}{I_L + I_0 - I_{mp}} - 2\frac{I_{mp} R_s}{n Ns V_{th}} = 0 $$

Copy link
Member Author

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))
Copy link
Member

@kandersolar kandersolar Feb 18, 2023

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.
Copy link
Member

@kandersolar kandersolar Feb 18, 2023

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

@cwhanse
Copy link
Member Author

cwhanse commented Feb 20, 2023

Shall we delete _golden_sect_DataFrame and _pwr_optfcn if they aren't used anywhere anymore?

I vote 'yes'

@cwhanse
Copy link
Member Author

cwhanse commented Feb 22, 2023

Moving this back to WIP, because I'm finding convergence problems with corner cases: Rsh=infinity, IL=0. Back to paper and pen.

@cwhanse cwhanse changed the title Speed up singlediode._lambertw WIP: Speed up singlediode._lambertw Feb 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Accelerate singlediode._lambertw
3 participants