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
28template <typename T>
29struct alignas(2*sizeof(T)) GpuComplex
30{
31 using value_type = T;
32
34
39 constexpr GpuComplex (const T& a_r = T(), const T& a_i = T()) noexcept
40 : m_real(a_r), m_imag(a_i) {}
41
46 constexpr T real () const noexcept { return m_real; }
47
52 constexpr T imag () const noexcept { return m_imag; }
53
57 template <typename U>
59 GpuComplex<T>& operator+= (const U& a_t) noexcept
60 {
61 m_real += a_t;
62 return *this;
63 }
64
68 template <typename U>
70 GpuComplex<T>& operator-= (const U& a_t) noexcept
71 {
72 m_real -= a_t;
73 return *this;
74 }
75
79 template <typename U>
81 GpuComplex<T>& operator*= (const U& a_t) noexcept
82 {
83 m_real *= a_t;
84 m_imag *= a_t;
85 return *this;
86 }
87
91 template <typename U>
93 GpuComplex<T>& operator/= (const U& a_t) noexcept
94 {
95 m_real /= a_t;
96 m_imag /= a_t;
97 return *this;
98 }
99
103 template <typename U>
106 {
107 m_real += a_z.real();
108 m_imag += a_z.imag();
109 return *this;
110 }
111
115 template <typename U>
118 {
119 m_real -= a_z.real();
120 m_imag -= a_z.imag();
121 return *this;
122 }
123
127 template <typename U>
130 {
131 const T a_r = m_real * a_z.real() - m_imag * a_z.imag();
132 m_imag = m_real * a_z.imag() + m_imag * a_z.real();
133 m_real = a_r;
134 return *this;
135 }
136
140 template <typename U>
143 {
144 const T r = m_real * a_z.real() + m_imag * a_z.imag();
145 const T n = amrex::norm(a_z);
146 m_imag = (m_imag * a_z.real() - m_real * a_z.imag()) / n;
147 m_real = r / n;
148 return *this;
149 }
150
154 template <typename U>
155 friend std::ostream & operator<< (std::ostream &out, const GpuComplex<U>& c);
156};
157
158template <typename U>
159std::ostream& operator<< (std::ostream& out, const GpuComplex<U>& c)
160{
161 out << c.m_real;
162 out << " + " << c.m_imag << "i";
163 return out;
164}
165
169template<typename T>
171GpuComplex<T> operator+ (const GpuComplex<T>& a_x) { return a_x; }
172
176template<typename T>
178GpuComplex<T> operator- (const GpuComplex<T>& a_x) { return GpuComplex<T>(-a_x.real(), -a_x.imag()); }
179
183template <typename T>
185GpuComplex<T> operator- (const GpuComplex<T>& a_x, const GpuComplex<T>& a_y) noexcept
186{
187 GpuComplex<T> r = a_x;
188 r -= a_y;
189 return r;
190}
191
195template <typename T>
197GpuComplex<T> operator- (const GpuComplex<T>& a_x, const T& a_y) noexcept
198{
199 GpuComplex<T> r = a_x;
200 r -= a_y;
201 return r;
202}
203
207template <typename T>
209GpuComplex<T> operator- (const T& a_x, const GpuComplex<T>& a_y) noexcept
210{
211 GpuComplex<T> r = a_y;
212 r -= a_x;
213 return -r;
214}
215
219template <typename T>
221GpuComplex<T> operator+ (const GpuComplex<T>& a_x, const GpuComplex<T>& a_y) noexcept
222{
223 GpuComplex<T> r = a_x;
224 r += a_y;
225 return r;
226}
227
231template <typename T>
233GpuComplex<T> operator+ (const GpuComplex<T>& a_x, const T& a_y) noexcept
234{
235 GpuComplex<T> r = a_x;
236 r += a_y;
237 return r;
238}
239
243template <typename T>
245GpuComplex<T> operator+ (const T& a_x, const GpuComplex<T>& a_y) noexcept
246{
247 GpuComplex<T> r = a_y;
248 r += a_x;
249 return r;
250}
251
255template <typename T, typename U>
257GpuComplex<T> operator* (const GpuComplex<T>& a_x, const GpuComplex<U>& a_y) noexcept
258{
259 GpuComplex<T> r = a_x;
260 r *= a_y;
261 return r;
262}
263
267template <typename T, typename U>
269GpuComplex<T> operator* (const GpuComplex<T>& a_x, const U& a_y) noexcept
270{
271 GpuComplex<T> r = a_x;
272 r *= a_y;
273 return r;
274}
275
279template <typename T>
281GpuComplex<T> operator* (const T& a_x, const GpuComplex<T>& a_y) noexcept
282{
283 GpuComplex<T> r = a_y;
284 r *= a_x;
285 return r;
286}
287
291template <typename T>
293GpuComplex<T> operator/ (const GpuComplex<T>& a_x, const GpuComplex<T>& a_y) noexcept
294{
295 GpuComplex<T> r = a_x;
296 r /= a_y;
297 return r;
298}
299
303template <typename T>
305GpuComplex<T> operator/ (const GpuComplex<T>& a_x, const T& a_y) noexcept
306{
307 GpuComplex<T> r = a_x;
308 r /= a_y;
309 return r;
310}
311
315template <typename T>
317GpuComplex<T> operator/ (const T& a_x, const GpuComplex<T>& a_y) noexcept
318{
319 GpuComplex<T> r = a_x;
320 r /= a_y;
321 return r;
322}
323
327template <typename T>
329GpuComplex<T> polar (const T& a_r, const T& a_theta) noexcept
330{
331 return GpuComplex<T>(a_r * std::cos(a_theta), a_r * std::sin(a_theta));
332}
333
337template <typename T>
339GpuComplex<T> exp (const GpuComplex<T>& a_z) noexcept
340{
341 return polar<T>(std::exp(a_z.real()), a_z.imag());
342}
343
347template <typename T>
349T norm (const GpuComplex<T>& a_z) noexcept
350{
351 const T x = a_z.real();
352 const T y = a_z.imag();
353 return x * x + y * y;
354}
355
359template <typename T>
361T abs (const GpuComplex<T>& a_z) noexcept
362{
363 T x = a_z.real();
364 T y = a_z.imag();
365
366 const T s = amrex::max(std::abs(x), std::abs(y));
367 if (s == T()) { return s; }
368 x /= s;
369 y /= s;
370 return s * std::sqrt(x * x + y * y);
371}
372
376template <typename T>
378GpuComplex<T> sqrt (const GpuComplex<T>& a_z) noexcept
379{
380 T x = a_z.real();
381 T y = a_z.imag();
382
383 if (x == T())
384 {
385 T t = std::sqrt(std::abs(y) / 2);
386 return GpuComplex<T>(t, y < T() ? -t : t);
387 }
388 else
389 {
390 T t = std::sqrt(2 * (amrex::abs(a_z) + std::abs(x)));
391 T u = t / 2;
392 return x > T()
393 ? GpuComplex<T>(u, y / t)
394 : GpuComplex<T>(std::abs(y) / t, y < T() ? -u : u);
395 }
396}
397
401template <typename T>
403T arg (const GpuComplex<T>& a_z) noexcept
404{
405 return std::atan2(a_z.imag(), a_z.real());
406}
407
411template <typename T>
413GpuComplex<T> log (const GpuComplex<T>& a_z) noexcept
414{
415 return GpuComplex<T>(std::log(amrex::abs(a_z)), amrex::arg(a_z));
416}
417
421template <typename T>
423GpuComplex<T> pow (const GpuComplex<T>& a_z, const T& a_y) noexcept
424{
425 if (a_z.imag() == T() && a_z.real() > T()) {
426 return std::pow(a_z.real(), a_y);
427 }
428
429 GpuComplex<T> t = amrex::log(a_z);
430 return amrex::polar<T>(std::exp(a_y * t.real()), a_y * t.imag());
431}
432
434namespace detail
435{
436 template <typename T>
438 GpuComplex<T> complex_pow_unsigned (GpuComplex<T> a_z, unsigned a_n)
439 {
440 GpuComplex<T> y = a_n % 2 ? a_z : GpuComplex<T>(1);
441
442 while (a_n >>= 1)
443 {
444 a_z *= a_z;
445 if (a_n % 2) {
446 y *= a_z;
447 }
448 }
449
450 return y;
451 }
452}
454
458template <typename T>
460GpuComplex<T> pow (const GpuComplex<T>& a_z, int a_n) noexcept
461{
462 return a_n < 0
463 ? GpuComplex<T>(1) / detail::complex_pow_unsigned(a_z, (unsigned)(-a_n))
464 : detail::complex_pow_unsigned(a_z, a_n);
465}
466
467}
468
469#endif
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:119
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
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:403
__host__ __device__ T norm(const GpuComplex< T > &a_z) noexcept
Return the norm (magnitude squared) of a complex number.
Definition AMReX_GpuComplex.H:349
__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:423
__host__ __device__ GpuComplex< T > operator*(const GpuComplex< T > &a_x, const GpuComplex< U > &a_y) noexcept
Multiply two complex numbers.
Definition AMReX_GpuComplex.H:257
__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:329
__host__ __device__ GpuComplex< T > log(const GpuComplex< T > &a_z) noexcept
Complex natural logarithm function.
Definition AMReX_GpuComplex.H:413
__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:361
__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:293
__host__ __device__ GpuComplex< T > exp(const GpuComplex< T > &a_z) noexcept
Complex expotential function.
Definition AMReX_GpuComplex.H:339
__host__ __device__ GpuComplex< T > sqrt(const GpuComplex< T > &a_z) noexcept
Return the square root of a complex number.
Definition AMReX_GpuComplex.H:378
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
A host / device complex number type, because std::complex doesn't work in device code with Cuda yet.
Definition AMReX_GpuComplex.H:30
__host__ __device__ GpuComplex< T > & operator*=(const U &a_t) noexcept
Multiply this complex number by a real.
Definition AMReX_GpuComplex.H:81
__host__ __device__ GpuComplex< T > & operator/=(const U &a_t) noexcept
Divide this complex number by a real.
Definition AMReX_GpuComplex.H:93
T m_imag
Definition AMReX_GpuComplex.H:33
friend std::ostream & operator<<(std::ostream &out, const GpuComplex< U > &c)
Print this complex number to an ostream.
Definition AMReX_GpuComplex.H:159
__host__ __device__ GpuComplex< T > & operator+=(const U &a_t) noexcept
Add a real number to this complex number.
Definition AMReX_GpuComplex.H:59
__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:39
T value_type
Definition AMReX_GpuComplex.H:31
__host__ __device__ constexpr T real() const noexcept
Return the real part.
Definition AMReX_GpuComplex.H:46
T m_real
Definition AMReX_GpuComplex.H:33
__host__ __device__ constexpr T imag() const noexcept
Return the imaginary part.
Definition AMReX_GpuComplex.H:52
__host__ __device__ GpuComplex< T > & operator-=(const U &a_t) noexcept
Subtract a real number from this complex number.
Definition AMReX_GpuComplex.H:70