Block-Structured AMR Software Framework
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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
57 GpuComplex<T>& operator+= (const T& a_t) noexcept
58 {
59 m_real += a_t;
60 return *this;
61 }
62
67 GpuComplex<T>& operator-= (const T& a_t) noexcept
68 {
69 m_real -= a_t;
70 return *this;
71 }
72
77 GpuComplex<T>& operator*= (const T& a_t) noexcept
78 {
79 m_real *= a_t;
80 m_imag *= a_t;
81 return *this;
82 }
83
88 GpuComplex<T>& operator/= (const T& a_t) noexcept
89 {
90 m_real /= a_t;
91 m_imag /= a_t;
92 return *this;
93 }
94
98 template <typename U>
101 {
102 m_real += a_z.real();
103 m_imag += a_z.imag();
104 return *this;
105 }
106
110 template <typename U>
113 {
114 m_real -= a_z.real();
115 m_imag -= a_z.imag();
116 return *this;
117 }
118
122 template <typename U>
125 {
126 const T a_r = m_real * a_z.real() - m_imag * a_z.imag();
127 m_imag = m_real * a_z.imag() + m_imag * a_z.real();
128 m_real = a_r;
129 return *this;
130 }
131
135 template <typename U>
138 {
139 const T r = m_real * a_z.real() + m_imag * a_z.imag();
140 const T n = amrex::norm(a_z);
141 m_imag = (m_imag * a_z.real() - m_real * a_z.imag()) / n;
142 m_real = r / n;
143 return *this;
144 }
145
149 template <typename U>
150 friend std::ostream & operator<< (std::ostream &out, const GpuComplex<U>& c);
151};
152
153template <typename U>
154std::ostream& operator<< (std::ostream& out, const GpuComplex<U>& c)
155{
156 out << c.m_real;
157 out << " + " << c.m_imag << "i";
158 return out;
159}
160
164template<typename T>
166GpuComplex<T> operator+ (const GpuComplex<T>& a_x) { return a_x; }
167
171template<typename T>
173GpuComplex<T> operator- (const GpuComplex<T>& a_x) { return GpuComplex<T>(-a_x.real(), -a_x.imag()); }
174
178template <typename T>
180GpuComplex<T> operator- (const GpuComplex<T>& a_x, const GpuComplex<T>& a_y) noexcept
181{
182 GpuComplex<T> r = a_x;
183 r -= a_y;
184 return r;
185}
186
190template <typename T>
192GpuComplex<T> operator- (const GpuComplex<T>& a_x, const T& a_y) noexcept
193{
194 GpuComplex<T> r = a_x;
195 r -= a_y;
196 return r;
197}
198
202template <typename T>
204GpuComplex<T> operator- (const T& a_x, const GpuComplex<T>& a_y) noexcept
205{
206 GpuComplex<T> r = a_y;
207 r -= a_x;
208 return -r;
209}
210
214template <typename T>
216GpuComplex<T> operator+ (const GpuComplex<T>& a_x, const GpuComplex<T>& a_y) noexcept
217{
218 GpuComplex<T> r = a_x;
219 r += a_y;
220 return r;
221}
222
226template <typename T>
228GpuComplex<T> operator+ (const GpuComplex<T>& a_x, const T& a_y) noexcept
229{
230 GpuComplex<T> r = a_x;
231 r += a_y;
232 return r;
233}
234
238template <typename T>
240GpuComplex<T> operator+ (const T& a_x, const GpuComplex<T>& a_y) noexcept
241{
242 GpuComplex<T> r = a_y;
243 r += a_x;
244 return r;
245}
246
250template <typename T>
252GpuComplex<T> operator* (const GpuComplex<T>& a_x, const GpuComplex<T>& a_y) noexcept
253{
254 GpuComplex<T> r = a_x;
255 r *= a_y;
256 return r;
257}
258
262template <typename T>
264GpuComplex<T> operator* (const GpuComplex<T>& a_x, const T& a_y) noexcept
265{
266 GpuComplex<T> r = a_x;
267 r *= a_y;
268 return r;
269}
270
274template <typename T>
276GpuComplex<T> operator* (const T& a_x, const GpuComplex<T>& a_y) noexcept
277{
278 GpuComplex<T> r = a_y;
279 r *= a_x;
280 return r;
281}
282
286template <typename T>
288GpuComplex<T> operator/ (const GpuComplex<T>& a_x, const GpuComplex<T>& a_y) noexcept
289{
290 GpuComplex<T> r = a_x;
291 r /= a_y;
292 return r;
293}
294
298template <typename T>
300GpuComplex<T> operator/ (const GpuComplex<T>& a_x, const T& a_y) noexcept
301{
302 GpuComplex<T> r = a_x;
303 r /= a_y;
304 return r;
305}
306
310template <typename T>
312GpuComplex<T> operator/ (const T& a_x, const GpuComplex<T>& a_y) noexcept
313{
314 GpuComplex<T> r = a_x;
315 r /= a_y;
316 return r;
317}
318
322template <typename T>
324GpuComplex<T> polar (const T& a_r, const T& a_theta) noexcept
325{
326 return GpuComplex<T>(a_r * std::cos(a_theta), a_r * std::sin(a_theta));
327}
328
332template <typename T>
334GpuComplex<T> exp (const GpuComplex<T>& a_z) noexcept
335{
336 return polar<T>(std::exp(a_z.real()), a_z.imag());
337}
338
342template <typename T>
344T norm (const GpuComplex<T>& a_z) noexcept
345{
346 const T x = a_z.real();
347 const T y = a_z.imag();
348 return x * x + y * y;
349}
350
354template <typename T>
356T abs (const GpuComplex<T>& a_z) noexcept
357{
358 T x = a_z.real();
359 T y = a_z.imag();
360
361 const T s = amrex::max(std::abs(x), std::abs(y));
362 if (s == T()) { return s; }
363 x /= s;
364 y /= s;
365 return s * std::sqrt(x * x + y * y);
366}
367
371template <typename T>
373GpuComplex<T> sqrt (const GpuComplex<T>& a_z) noexcept
374{
375 T x = a_z.real();
376 T y = a_z.imag();
377
378 if (x == T())
379 {
380 T t = std::sqrt(std::abs(y) / 2);
381 return GpuComplex<T>(t, y < T() ? -t : t);
382 }
383 else
384 {
385 T t = std::sqrt(2 * (amrex::abs(a_z) + std::abs(x)));
386 T u = t / 2;
387 return x > T()
388 ? GpuComplex<T>(u, y / t)
389 : GpuComplex<T>(std::abs(y) / t, y < T() ? -u : u);
390 }
391}
392
396template <typename T>
398T arg (const GpuComplex<T>& a_z) noexcept
399{
400 return std::atan2(a_z.imag(), a_z.real());
401}
402
406template <typename T>
408GpuComplex<T> log (const GpuComplex<T>& a_z) noexcept
409{
410 return GpuComplex<T>(std::log(amrex::abs(a_z)), amrex::arg(a_z));
411}
412
416template <typename T>
418GpuComplex<T> pow (const GpuComplex<T>& a_z, const T& a_y) noexcept
419{
420 if (a_z.imag() == T() && a_z.real() > T()) {
421 return std::pow(a_z.real(), a_y);
422 }
423
424 GpuComplex<T> t = amrex::log(a_z);
425 return amrex::polar<T>(std::exp(a_y * t.real()), a_y * t.imag());
426}
427
428namespace detail
429{
430 template <typename T>
433 {
434 GpuComplex<T> y = a_n % 2 ? a_z : GpuComplex<T>(1);
435
436 while (a_n >>= 1)
437 {
438 a_z *= a_z;
439 if (a_n % 2) {
440 y *= a_z;
441 }
442 }
443
444 return y;
445 }
446}
447
451template <typename T>
453GpuComplex<T> pow (const GpuComplex<T>& a_z, int a_n) noexcept
454{
455 return a_n < 0
456 ? GpuComplex<T>(1) / detail::complex_pow_unsigned(a_z, (unsigned)(-a_n))
458}
459
460}
461
462#endif
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:119
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE GpuComplex< T > complex_pow_unsigned(GpuComplex< T > a_z, unsigned a_n)
Definition AMReX_GpuComplex.H:432
Definition AMReX_Amr.cpp:49
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE GpuComplex< T > log(const GpuComplex< T > &a_z) noexcept
Complex natural logarithm function.
Definition AMReX_GpuComplex.H:408
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE GpuComplex< T > operator+(const GpuComplex< T > &a_x)
Identity operation on a complex number.
Definition AMReX_GpuComplex.H:166
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE T abs(const GpuComplex< T > &a_z) noexcept
Return the absolute value of a complex number.
Definition AMReX_GpuComplex.H:356
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE GpuComplex< T > sqrt(const GpuComplex< T > &a_z) noexcept
Return the square root of a complex number.
Definition AMReX_GpuComplex.H:373
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE GpuComplex< T > exp(const GpuComplex< T > &a_z) noexcept
Complex expotential function.
Definition AMReX_GpuComplex.H:334
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE GpuComplex< T > operator*(const GpuComplex< T > &a_x, const GpuComplex< T > &a_y) noexcept
Multiply two complex numbers.
Definition AMReX_GpuComplex.H:252
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE T norm(const GpuComplex< T > &a_z) noexcept
Return the norm (magnitude squared) of a complex number.
Definition AMReX_GpuComplex.H:344
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE T arg(const GpuComplex< T > &a_z) noexcept
Return the angle of a complex number's polar representation.
Definition AMReX_GpuComplex.H:398
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE 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:288
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE 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:418
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr const T & max(const T &a, const T &b) noexcept
Definition AMReX_Algorithm.H:35
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE GpuComplex< T > polar(const T &a_r, const T &a_theta) noexcept
Return a complex number given its polar representation.
Definition AMReX_GpuComplex.H:324
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE GpuComplex< T > operator-(const GpuComplex< T > &a_x)
Negate a complex number.
Definition AMReX_GpuComplex.H:173
std::ostream & operator<<(std::ostream &os, AmrMesh const &amr_mesh)
Definition AMReX_AmrMesh.cpp:1236
Definition AMReX_FabArrayCommI.H:896
A host / device complex number type, because std::complex doesn't work in device code with Cuda yet.
Definition AMReX_GpuComplex.H:29
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr T real() const noexcept
Return the real part.
Definition AMReX_GpuComplex.H:45
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr T imag() const noexcept
Return the imaginary part.
Definition AMReX_GpuComplex.H:51
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE GpuComplex< T > & operator+=(const T &a_t) noexcept
Add a real number to this complex number.
Definition AMReX_GpuComplex.H:57
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE GpuComplex< T > & operator/=(const T &a_t) noexcept
Divide this complex number by a real.
Definition AMReX_GpuComplex.H:88
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE GpuComplex< T > & operator*=(const T &a_t) noexcept
Multiply this complex number by a real.
Definition AMReX_GpuComplex.H:77
T m_imag
Definition AMReX_GpuComplex.H:32
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE GpuComplex< T > & operator-=(const T &a_t) noexcept
Subtract a real number from this complex number.
Definition AMReX_GpuComplex.H:67
friend std::ostream & operator<<(std::ostream &out, const GpuComplex< U > &c)
Print this complex number to an ostream.
Definition AMReX_GpuComplex.H:154
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE 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
T m_real
Definition AMReX_GpuComplex.H:32