-
Notifications
You must be signed in to change notification settings - Fork 349
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
Adding computation of complete elliptic integrals into amrex::Math so… #4151
Changes from 3 commits
3f26f10
d0390fd
093a2cc
f77df48
1819253
4cfc9b8
239b3bb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
#include <AMReX_GpuQualifiers.H> | ||
#include <AMReX_Extension.H> | ||
#include <AMReX_INT.H> | ||
#include <AMReX_REAL.H> | ||
#include <cmath> | ||
#include <cstdlib> | ||
#include <type_traits> | ||
|
@@ -225,6 +226,70 @@ std::uint64_t umulhi (std::uint64_t a, std::uint64_t b) | |
} | ||
#endif | ||
|
||
template <typename T> | ||
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE | ||
T comp_ellint_1 (T m) | ||
{ | ||
// Computing K based on DLMF | ||
// https://dlmf.nist.gov/19.8 | ||
T tol = 1e-12; | ||
T a0 = 1.0; | ||
T g0 = std::sqrt(1.0 - m); | ||
T a, g; | ||
|
||
// Find Arithmetic Geometric mean | ||
while(std::abs(a0 - g0) > tol) { | ||
a = 0.5*(a0 + g0); | ||
g = std::sqrt(a0 * g0); | ||
|
||
a0 = a; | ||
g0 = g; | ||
} | ||
|
||
return 0.5*pi<T>()/a; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If m is 0, a is uninitialized. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a definition issue. In most cases the integrals are defined with m as the argument. In this case with gcc it is k = sqrt(m). I will update it to be consistent and I will additionally add some test figures doing comparisons. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @WeiqunZhang in general though do you think this is the right spot for this calculation? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I think so. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems that we could use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The above figure is the difference between the two cases for the Z-components of the analytical solution to a current loop. |
||
} | ||
|
||
template <typename T> | ||
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE | ||
T comp_ellint_2 (T m) | ||
{ | ||
// Computing E based on DLMF | ||
// https://dlmf.nist.gov/19.8 | ||
T Kcomp = amrex::Math::comp_ellint_1<T>(m); | ||
T tol = 1e-12; | ||
|
||
// Step Zero | ||
T a0 = 1.0; | ||
T g0 = std::sqrt(1.0 - m); | ||
T cn = std::sqrt(a0*a0 - g0*g0); | ||
|
||
// Step 1 | ||
int n = 1; | ||
T a = 0.5 * (a0 + g0); | ||
T g = std::sqrt(a0*g0); | ||
cn = 0.25*cn*cn/a; | ||
|
||
T sum_val = a*a; | ||
a0 = a; | ||
g0 = g; | ||
|
||
while(std::abs(cn*cn) > tol) { | ||
// Compute coefficients for this iteration | ||
a = 0.5 * (a0 + g0); | ||
g = std::sqrt(a0*g0); | ||
cn = 0.25*cn*cn/a; | ||
|
||
n++; | ||
sum_val -= std::pow(2,n-1)*cn*cn; | ||
|
||
// Save a and g for next iteration | ||
a0 = a; | ||
g0 = g; | ||
} | ||
|
||
return Kcomp*sum_val; | ||
} | ||
|
||
/*************************************************************************************************** | ||
* Copyright (c) 2017 - 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
|
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.
What if T is float?
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 will add a check on it to adjust the tolerance for a float to 1e-6.
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 should be fixed now.