Block-Structured AMR Software Framework
 
Loading...
Searching...
No Matches
AMReX_GpuComplex.H
Go to the documentation of this file.
1#ifndef AMREX_GPUCOMPLEX_H_
2#define AMREX_GPUCOMPLEX_H_
3#include <AMReX_Config.H>
4
5#include <AMReX_Algorithm.H>
6#include <AMReX_Math.H>
7#include <cmath>
8#include <iostream>
9
10namespace amrex {
11
12template <typename T> struct GpuComplex;
13
14template <typename T>
16T norm (const GpuComplex<T>& a_z) noexcept;
17
27template <typename T>
28struct alignas(2*sizeof(T)) GpuComplex
29{
30 using value_type = T;
31
33
38 constexpr GpuComplex (const T& a_r = T(), const T& a_i = T()) noexcept
39 : m_real(a_r), m_imag(a_i) {}
40
45 constexpr T real () const noexcept { return m_real; }
46
51 constexpr T imag () const noexcept { return m_imag; }
52
56 template <typename U>
58 GpuComplex<T>& operator+= (const U& a_t) noexcept
59 {
60 m_real += a_t;
61 return *this;
62 }
63
67 template <typename U>
69 GpuComplex<T>& operator-= (const U& a_t) noexcept
70 {
71 m_real -= a_t;
72 return *this;
73 }
74
78 template <typename U>
80 GpuComplex<T>& operator*= (const U& a_t) noexcept
81 {
82 m_real *= a_t;
83 m_imag *= a_t;
84 return *this;
85 }
86
90 template <typename U>
92 GpuComplex<T>& operator/= (const U& a_t) noexcept
93 {
94 m_real /= a_t;
95 m_imag /= a_t;
96 return *this;
97 }
98
102 template <typename U>
105 {
106 m_real += a_z.real();
107 m_imag += a_z.imag();
108 return *this;
109 }
110
114 template <typename U>
117 {
118 m_real -= a_z.real();
119 m_imag -= a_z.imag();
120 return *this;
121 }
122
126 template <typename U>
129 {
130 const T a_r = m_real * a_z.real() - m_imag * a_z.imag();
131 m_imag = m_real * a_z.imag() + m_imag * a_z.real();
132 m_real = a_r;
133 return *this;
134 }
135
139 template <typename U>
142 {
143 const T r = m_real * a_z.real() + m_imag * a_z.imag();
144 const T n = amrex::norm(a_z);
145 m_imag = (m_imag * a_z.real() - m_real * a_z.imag()) / n;
146 m_real = r / n;
147 return *this;
148 }
149
153 template <typename U>
154 friend std::ostream & operator<< (std::ostream &out, const GpuComplex<U>& c);
155};
156
157template <typename U>
158std::ostream& operator<< (std::ostream& out, const GpuComplex<U>& c)
159{
160 out << c.m_real;
161 out << " + " << c.m_imag << "i";
162 return out;
163}
164
168template<typename T>
170GpuComplex<T> operator+ (const GpuComplex<T>& a_x) { return a_x; }
171
175template<typename T>
177GpuComplex<T> operator- (const GpuComplex<T>& a_x) { return GpuComplex<T>(-a_x.real(), -a_x.imag()); }
178
182template <typename T>
184GpuComplex<T> operator- (const GpuComplex<T>& a_x, const GpuComplex<T>& a_y) noexcept
185{
186 GpuComplex<T> r = a_x;
187 r -= a_y;
188 return r;
189}
190
194template <typename T>
196GpuComplex<T> operator- (const GpuComplex<T>& a_x, const T& a_y) noexcept
197{
198 GpuComplex<T> r = a_x;
199 r -= a_y;
200 return r;
201}
202
206template <typename T>
208GpuComplex<T> operator- (const T& a_x, const GpuComplex<T>& a_y) noexcept
209{
210 GpuComplex<T> r = a_y;
211 r -= a_x;
212 return -r;
213}
214
218template <typename T>
220GpuComplex<T> operator+ (const GpuComplex<T>& a_x, const GpuComplex<T>& a_y) noexcept
221{
222 GpuComplex<T> r = a_x;
223 r += a_y;
224 return r;
225}
226
230template <typename T>
232GpuComplex<T> operator+ (const GpuComplex<T>& a_x, const T& a_y) noexcept
233{
234 GpuComplex<T> r = a_x;
235 r += a_y;
236 return r;
237}
238
242template <typename T>
244GpuComplex<T> operator+ (const T& a_x, const GpuComplex<T>& a_y) noexcept
245{
246 GpuComplex<T> r = a_y;
247 r += a_x;
248 return r;
249}
250
254template <typename T, typename U>
256GpuComplex<T> operator* (const GpuComplex<T>& a_x, const GpuComplex<U>& a_y) noexcept
257{
258 GpuComplex<T> r = a_x;
259 r *= a_y;
260 return r;
261}
262
266template <typename T, typename U>
268GpuComplex<T> operator* (const GpuComplex<T>& a_x, const U& a_y) noexcept
269{
270 GpuComplex<T> r = a_x;
271 r *= a_y;
272 return r;
273}
274
278template <typename T>
280GpuComplex<T> operator* (const T& a_x, const GpuComplex<T>& a_y) noexcept
281{
282 GpuComplex<T> r = a_y;
283 r *= a_x;
284 return r;
285}
286
290template <typename T>
292GpuComplex<T> operator/ (const GpuComplex<T>& a_x, const GpuComplex<T>& a_y) noexcept
293{
294 GpuComplex<T> r = a_x;
295 r /= a_y;
296 return r;
297}
298
302template <typename T>
304GpuComplex<T> operator/ (const GpuComplex<T>& a_x, const T& a_y) noexcept
305{
306 GpuComplex<T> r = a_x;
307 r /= a_y;
308 return r;
309}
310
314template <typename T>
316GpuComplex<T> operator/ (const T& a_x, const GpuComplex<T>& a_y) noexcept
317{
318 GpuComplex<T> r = a_x;
319 r /= a_y;
320 return r;
321}
322
326template <typename T>
328GpuComplex<T> polar (const T& a_r, const T& a_theta) noexcept
329{
330 return GpuComplex<T>(a_r * std::cos(a_theta), a_r * std::sin(a_theta));
331}
332
336template <typename T>
338GpuComplex<T> exp (const GpuComplex<T>& a_z) noexcept
339{
340 return polar<T>(std::exp(a_z.real()), a_z.imag());
341}
342
346template <typename T>
348T norm (const GpuComplex<T>& a_z) noexcept
349{
350 const T x = a_z.real();
351 const T y = a_z.imag();
352 return x * x + y * y;
353}
354
358template <typename T>
360T abs (const GpuComplex<T>& a_z) noexcept
361{
362 T x = a_z.real();
363 T y = a_z.imag();
364
365 const T s = amrex::max(std::abs(x), std::abs(y));
366 if (s == T()) { return s; }
367 x /= s;
368 y /= s;
369 return s * std::sqrt(x * x + y * y);
370}
371
375template <typename T>
377GpuComplex<T> sqrt (const GpuComplex<T>& a_z) noexcept
378{
379 T x = a_z.real();
380 T y = a_z.imag();
381
382 if (x == T())
383 {
384 T t = std::sqrt(std::abs(y) / 2);
385 return GpuComplex<T>(t, y < T() ? -t : t);
386 }
387 else
388 {
389 T t = std::sqrt(2 * (amrex::abs(a_z) + std::abs(x)));
390 T u = t / 2;
391 return x > T()
392 ? GpuComplex<T>(u, y / t)
393 : GpuComplex<T>(std::abs(y) / t, y < T() ? -u : u);
394 }
395}
396
400template <typename T>
402T arg (const GpuComplex<T>& a_z) noexcept
403{
404 return std::atan2(a_z.imag(), a_z.real());
405}
406
410template <typename T>
412GpuComplex<T> log (const GpuComplex<T>& a_z) noexcept
413{
414 return GpuComplex<T>(std::log(amrex::abs(a_z)), amrex::arg(a_z));
415}
416
420template <typename T>
422GpuComplex<T> pow (const GpuComplex<T>& a_z, const T& a_y) noexcept
423{
424 if (a_z.imag() == T() && a_z.real() > T()) {
425 return std::pow(a_z.real(), a_y);
426 }
427
428 GpuComplex<T> t = amrex::log(a_z);
429 return amrex::polar<T>(std::exp(a_y * t.real()), a_y * t.imag());
430}
431
432namespace detail
433{
434 template <typename T>
437 {
438 GpuComplex<T> y = a_n % 2 ? a_z : GpuComplex<T>(1);
439
440 while (a_n >>= 1)
441 {
442 a_z *= a_z;
443 if (a_n % 2) {
444 y *= a_z;
445 }
446 }
447
448 return y;
449 }
450}
451
455template <typename T>
457GpuComplex<T> pow (const GpuComplex<T>& a_z, int a_n) noexcept
458{
459 return a_n < 0
460 ? GpuComplex<T>(1) / detail::complex_pow_unsigned(a_z, (unsigned)(-a_n))
462}
463
464}
465
466#endif
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:119
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
__host__ __device__ GpuComplex< T > complex_pow_unsigned(GpuComplex< T > a_z, unsigned a_n)
Definition AMReX_GpuComplex.H:436
Definition AMReX_Amr.cpp:49
__host__ __device__ T arg(const GpuComplex< T > &a_z) noexcept
Return the angle of a complex number's polar representation.
Definition AMReX_GpuComplex.H:402
__host__ __device__ T norm(const GpuComplex< T > &a_z) noexcept
Return the norm (magnitude squared) of a complex number.
Definition AMReX_GpuComplex.H:348
__host__ __device__ GpuComplex< T > pow(const GpuComplex< T > &a_z, const T &a_y) noexcept
Raise a complex number to a (real) power.
Definition AMReX_GpuComplex.H:422
__host__ __device__ GpuComplex< T > operator*(const GpuComplex< T > &a_x, const GpuComplex< U > &a_y) noexcept
Multiply two complex numbers.
Definition AMReX_GpuComplex.H:256
__host__ __device__ GpuComplex< T > polar(const T &a_r, const T &a_theta) noexcept
Return a complex number given its polar representation.
Definition AMReX_GpuComplex.H:328
__host__ __device__ GpuComplex< T > log(const GpuComplex< T > &a_z) noexcept
Complex natural logarithm function.
Definition AMReX_GpuComplex.H:412
__host__ __device__ constexpr const T & max(const T &a, const T &b) noexcept
Definition AMReX_Algorithm.H:35
__host__ __device__ T abs(const GpuComplex< T > &a_z) noexcept
Return the absolute value of a complex number.
Definition AMReX_GpuComplex.H:360
__host__ __device__ GpuComplex< T > operator/(const GpuComplex< T > &a_x, const GpuComplex< T > &a_y) noexcept
Divide a complex number by another one.
Definition AMReX_GpuComplex.H:292
__host__ __device__ GpuComplex< T > exp(const GpuComplex< T > &a_z) noexcept
Complex expotential function.
Definition AMReX_GpuComplex.H:338
__host__ __device__ GpuComplex< T > sqrt(const GpuComplex< T > &a_z) noexcept
Return the square root of a complex number.
Definition AMReX_GpuComplex.H:377
std::ostream & operator<<(std::ostream &os, AmrMesh const &amr_mesh)
Definition AMReX_AmrMesh.cpp:1236
__host__ __device__ XDim3 operator-(XDim3 const &a, XDim3 const &b)
Definition AMReX_Dim3.H:34
__host__ __device__ XDim3 operator+(XDim3 const &a, XDim3 const &b)
Definition AMReX_Dim3.H:28
Definition AMReX_FabArrayCommI.H:1000
A host / device complex number type, because std::complex doesn't work in device code with Cuda yet.
Definition AMReX_GpuComplex.H:29
__host__ __device__ GpuComplex< T > & operator*=(const U &a_t) noexcept
Multiply this complex number by a real.
Definition AMReX_GpuComplex.H:80
__host__ __device__ GpuComplex< T > & operator/=(const U &a_t) noexcept
Divide this complex number by a real.
Definition AMReX_GpuComplex.H:92
T m_imag
Definition AMReX_GpuComplex.H:32
friend std::ostream & operator<<(std::ostream &out, const GpuComplex< U > &c)
Print this complex number to an ostream.
Definition AMReX_GpuComplex.H:158
__host__ __device__ GpuComplex< T > & operator+=(const U &a_t) noexcept
Add a real number to this complex number.
Definition AMReX_GpuComplex.H:58
__host__ __device__ constexpr GpuComplex(const T &a_r=T(), const T &a_i=T()) noexcept
Construct a complex number given the real and imaginary part.
Definition AMReX_GpuComplex.H:38
T value_type
Definition AMReX_GpuComplex.H:30
__host__ __device__ constexpr T real() const noexcept
Return the real part.
Definition AMReX_GpuComplex.H:45
T m_real
Definition AMReX_GpuComplex.H:32
__host__ __device__ constexpr T imag() const noexcept
Return the imaginary part.
Definition AMReX_GpuComplex.H:51
__host__ __device__ GpuComplex< T > & operator-=(const U &a_t) noexcept
Subtract a real number from this complex number.
Definition AMReX_GpuComplex.H:69