question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

use horners method in DISC instead of calculating so many powers and polynomials

See original GitHub issue

Describe the bug the disc method has a lot of power and polynomials. IMO whenever possible, polynomials should use Horner’s method which is already implemented in np.polyval but is easy to reimplement if needed.

To Reproduce https://github.com/pvlib/pvlib-python/blob/8b98768818ee5ad85d9479877533651a2e9dc2cd/pvlib/irradiance.py#L1405-L1422

0.512 - 1.56*kt + 2.286*kt2 - 2.222*kt3

becomes

0.512 - kt * (1.56 + kt * (2.286 - 2.222 * kt))

or

np.polyval([-2.222, 2.286, -1.56, 0.512], kt)

Expected behavior a few math tricks like this (atan2, log1p, Horner’s method, etc.) are musts for efficiency and numerical stability.

Versions:

  • pvlib.__version__: 0.8.1

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:7 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
adriessecommented, Mar 18, 2021

Miscellaneous observations:

  • Since kt is in the range 0-1 I would not expect numerical issues with any evaluation method. Air mass in the range 1-40 should be fine too.
  • For speed, you could also look into using np.dot with the factors.
  • The average scientist or student exploring the inner workings of pvlib will probably find the original easiest to understand.
  • Thinking about code clarity, you could consider changing the name bools to is_cloudy.
1reaction
mikofskicommented, Feb 27, 2021

I counted and surprisingly, there are the same flops in the existing kt, kt2, kt3 code than in Horner’s, in fact, there are exactly 3 more, because it’s unnecessary to pre-calculate kt, kt2, kt3 when using Horner’s

By the numbers:

In [3]: kt = np.linspace(0.1, 0.9, 90)

In [4]: %paste
def test1(kt):
    kt2 = kt * kt  # about the same as kt ** 2
    kt3 = kt2 * kt  # 5-10x faster than kt ** 3

    bools = (kt <= 0.6)
    a = np.where(bools,
              0.512 - 1.56*kt + 2.286*kt2 - 2.222*kt3,
              -5.743 + 21.77*kt - 27.49*kt2 + 11.56*kt3)
    b = np.where(bools,
              0.37 + 0.962*kt,
              41.4 - 118.5*kt + 66.05*kt2 + 31.9*kt3)
    c = np.where(bools,
              -0.28 + 0.932*kt - 2.048*kt2,
              -47.01 + 184.2*kt - 222.0*kt2 + 73.81*kt3)
    return a, b, c

## -- End pasted text --

In [7]: a, b, c = test1(kt)

In [9]: %paste
def test2(kt):
    bools = (kt <= 0.6)
    a = np.where(bools,
              0.512 + kt*(-1.56 + kt*(2.286 - 2.222*kt)),
              -5.743 + kt*(21.77 + kt*(-27.49 + 11.56*kt)))
    b = np.where(bools,
              0.37 + 0.962*kt,
              41.4 + kt*(-118.5 + kt*(66.05 + 31.9*kt)))
    c = np.where(bools,
              -0.28 + kt*(0.932 - 2.048*kt),
              -47.01 + kt*(184.2 + kt*(-222.0 + 73.81*kt)))
    return a, b, c

## -- End pasted text --

In [10]: x, y, z = test2(kt)

In [11]: np.allclose(a,x)
Out[11]: True

In [12]: np.allclose(b,y)
Out[12]: True

In [13]: np.allclose(c,z)
Out[13]: True

In [14]: %timeit test2(kt)
23.3 µs ± 348 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [15]: %timeit test2(kt)
23.9 µs ± 462 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [16]: %timeit test1(kt)
26.2 µs ± 179 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [17]: %timeit test1(kt)
27.3 µs ± 661 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Surprise! Horners is about 10% faster for this part of the DISC too!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Horner's Method for Polynomial Evaluation - GeeksforGeeks
A naive way to evaluate a polynomial is to one by one evaluate all terms. First calculate x n, multiply the value with...
Read more >
Horner's method - Wikipedia
In mathematics and computer science, Horner's method (or Horner's scheme) is an algorithm for polynomial evaluation. Although named after William George ...
Read more >
Methods for evaluating polynomials quickly
Methods for evaluating polynomials quickly · 3. Horner's method. · 1. If it you happen to know that the powers are large compared...
Read more >
Horner's Method - YouTube
Horner's Method (Ruffini-Horner Scheme) for evaluating polynomials including a brief history, examples, Ruffini's Rule with derivatives, ...
Read more >
Horner's Method 2: Why it works for computing function values
This video explains a quicker method of computing function values of a polynomial. This method, also known as synthetic substitution, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found