Skip to content
Snippets Groups Projects

Periodic gravity speed and accuracy improvements

Merged Matthieu Schaller requested to merge periodic_gravity into master

Merge request reports

Loading
Loading

Activity

Filter activity
  • Approvals
  • Assignees & reviewers
  • Comments (from bots)
  • Comments (from users)
  • Commits & branches
  • Edits
  • Labels
  • Lock status
  • Mentions
  • Merge request status
  • Tracking
36 36 return 1.f + x * (1.f + x * (0.5f + x * (1.f / 6.f + 1.f / 24.f * x)));
37 37 }
38 38
39 /**
40 * @brief Approximate version of expf(x) using a 6th order Taylor expansion
41 *
42 */
43 __attribute__((always_inline)) INLINE static float good_approx_expf(float x) {
  • what kind of accuracy are you looking for in what range? there's likely a lower-degree polynomial for that specific case...

  • Matthieu Schaller
    Matthieu Schaller @matthieu started a thread on commit c8b6c872
  • 36 36 return 1.f + x * (1.f + x * (0.5f + x * (1.f / 6.f + 1.f / 24.f * x)));
    37 37 }
    38 38
    39 /**
    40 * @brief Approximate version of expf(x) using a 6th order Taylor expansion
    41 *
    42 */
    43 __attribute__((always_inline)) INLINE static float good_approx_expf(float x) {
    • Actually, I need the best possible approximation to e^x / ( 1+e^x ) for x in [0, 6]. It can just be 1 for any large x and I don't care about negative values. Might be that there is a Pade approximant of order less than 6 that does better than my current use of the approximate exp(). Note though that I can re-use the same exp(x) in both the numerator and denominator.

      I need to work out the approximation quality I need. Essentially if I am close enough to the true value then I can use the analytic expression for the corresponding function in Fourier space. This is already much much faster than before.

      I need to work out what "close enough" means though in terms of accuracy of the whole method.

      Edited by Matthieu Schaller
  • Matthieu Schaller
    Matthieu Schaller @matthieu started a thread on commit c8b6c872
  • 36 36 return 1.f + x * (1.f + x * (0.5f + x * (1.f / 6.f + 1.f / 24.f * x)));
    37 37 }
    38 38
    39 /**
    40 * @brief Approximate version of expf(x) using a 6th order Taylor expansion
    41 *
    42 */
    43 __attribute__((always_inline)) INLINE static float good_approx_expf(float x) {
    • One more thing: With this choice of function and the right coefficients, you can show that the correction factor is close to 1 (within less than 0.001) for all distances that are less than 0.1 of the mesh cell size. That means that for all self/pairs that take place at 4 levels or more below the top-level of the tree (where the FFT is performed), there is no need to compute any of this. With the erf choice, this is only true at 0.005 of the top-level mesh size, which is rarely reached.

      This feature comes from the sharper transition of this function compared to the erf and allows to avoid computing any of these terms for most of the interesting situations.

      I still need to write the bit of code that exploits this feature but it will make most of the discussion less relevant.

  • Pedro Gonnet
    Pedro Gonnet @nnrw56 started a thread on commit c8b6c872
  • 36 36 return 1.f + x * (1.f + x * (0.5f + x * (1.f / 6.f + 1.f / 24.f * x)));
    37 37 }
    38 38
    39 /**
    40 * @brief Approximate version of expf(x) using a 6th order Taylor expansion
    41 *
    42 */
    43 __attribute__((always_inline)) INLINE static float good_approx_expf(float x) {
    • well, it just so happens that i know a thing or two about rational/padé interpolation :smiley:

      let me see what i can do about exp(x)/(1+exp(x)). i'll start by aiming for single-precision accuracy and we can take it from there.

  • Matthieu Schaller
    Matthieu Schaller @matthieu started a thread on commit c8b6c872
  • 36 36 return 1.f + x * (1.f + x * (0.5f + x * (1.f / 6.f + 1.f / 24.f * x)));
    37 37 }
    38 38
    39 /**
    40 * @brief Approximate version of expf(x) using a 6th order Taylor expansion
    41 *
    42 */
    43 __attribute__((always_inline)) INLINE static float good_approx_expf(float x) {
    • Alright, then lets spice it up a bit. :smile:

      We also need to evaluate the first few derivatives of that thing for the multipole-multipole part of the calculation. The formulation I currently use is good as it does not require me to recompute more things. I can just build them using powers of 1 / ( 1 + e^x ). I think that this is a nice property to retain.

  • Matthieu Schaller Added 66 commits:

    Added 66 commits:

  • Added 1 commit:

  • Matthieu Schaller Status changed to merged

    Status changed to merged

  • mentioned in commit eef5614e

  • Please register or sign in to reply
    Loading