ImpactX
Toggle main menu visibility
Loading...
Searching...
No Matches
src
diagnostics
CovarianceMatrixMath.H
Go to the documentation of this file.
1
/* Copyright 2022-2026 The Regents of the University of California, through Lawrence
2
* Berkeley National Laboratory (subject to receipt of any required
3
* approvals from the U.S. Dept. of Energy). All rights reserved.
4
*
5
* This file is part of ImpactX.
6
*
7
* Authors: Chad Mitchell, Axel Huebl
8
* License: BSD-3-Clause-LBNL
9
*/
10
#ifndef COVARIANCE_MATRIX_MATH_H
11
#define COVARIANCE_MATRIX_MATH_H
12
13
#include <
ablastr/constant.H
>
14
#include <
ablastr/warn_manager/WarnManager.H
>
15
16
#include <
AMReX_REAL.H
>
17
#include <
AMReX_GpuComplex.H
>
18
#include <
AMReX_Math.H
>
19
20
#include <cmath>
21
#include <tuple>
22
23
24
namespace
impactx::diagnostics
25
{
26
38
std::tuple<
39
amrex::ParticleReal
,
40
amrex::ParticleReal
,
41
amrex::ParticleReal
42
>
43
CubicRootsTrig
(
44
amrex::ParticleReal
a,
45
amrex::ParticleReal
b,
46
amrex::ParticleReal
c,
47
amrex::ParticleReal
d
48
)
49
{
50
using namespace
amrex::literals
;
51
using
amrex::Math::powi
;
52
using
ablastr::constant::math::pi
;
53
54
std::tuple<amrex::ParticleReal, amrex::ParticleReal, amrex::ParticleReal> roots;
55
amrex::ParticleReal
x1 = 0.0_prt;
56
amrex::ParticleReal
x2 = 0.0_prt;
57
amrex::ParticleReal
x3 = 0.0_prt;
58
59
amrex::ParticleReal
Q = (3.0_prt*a*c - powi<2>(b))/(9.0_prt * powi<2>(a));
60
amrex::ParticleReal
R = (9.0_prt*a*b*c - 27_prt*powi<2>(a)*d - 2.0_prt*powi<3>(b))/(54.0_prt*powi<3>(a));
61
amrex::ParticleReal
discriminant = powi<3>(Q) + powi<2>(R);
62
63
// Discriminant should be < 0. Otherwise, keep theta at default and throw an error.
64
amrex::ParticleReal
tol = 1.0e-12_prt;
//allow for roundoff error
65
if
(discriminant > tol) {
66
67
ablastr::warn_manager::WMRecordWarning
(
68
"Impactx::diagnostics::CubicRootsTrig"
,
69
"Polynomial appearing in CubicRootsTrig has one or more complex "
70
"(non-real) roots. Only the real part is returned. This "
71
"suggests a loss of numerical precision in computation of the "
72
"eigenemittances. Treat eigenemittance values with caution."
,
73
ablastr::warn_manager::WarnPriority::medium
74
);
75
76
std::cout <<
"Polynomial in CubicRoots has one or more complex roots."
<<
"\n"
;
77
78
}
else
if
(Q == 0.0_prt) {
// Special case of a triple root
79
80
x1 = - b/(3.0_prt*a);
81
x2 = - b/(3.0_prt*a);
82
x3 = - b/(3.0_prt*a);
83
84
}
else
{
85
86
//Three real roots in trigonometric form.
87
amrex::ParticleReal
theta = std::acos(R/std::sqrt(-powi<3>(Q)));
88
x1 = 2.0_prt*std::sqrt(-Q)*std::cos(theta/3.0_prt) - b/(3.0_prt*a);
89
x2 = 2.0_prt*std::sqrt(-Q)*std::cos(theta/3.0_prt + 2.0_prt*pi/3.0_prt) - b/(3.0_prt*a);
90
x3 = 2.0_prt*std::sqrt(-Q)*std::cos(theta/3.0_prt + 4.0_prt*pi/3.0_prt) - b/(3.0_prt*a);
91
92
}
93
94
roots = std::make_tuple(x1,x2,x3);
95
return
roots;
96
}
97
98
110
std::tuple<
111
amrex::ParticleReal
,
112
amrex::ParticleReal
,
113
amrex::ParticleReal
114
>
115
CubicRootsAlg
(
116
amrex::ParticleReal
a,
117
amrex::ParticleReal
b,
118
amrex::ParticleReal
c,
119
amrex::ParticleReal
d
120
)
121
{
122
using namespace
amrex::literals
;
123
using
amrex::Math::powi
;
124
using
Complex
=
amrex::GpuComplex<amrex::ParticleReal>
;
125
126
std::tuple<amrex::ParticleReal, amrex::ParticleReal, amrex::ParticleReal> roots;
127
amrex::ParticleReal
x1 = 0_prt;
128
amrex::ParticleReal
x2 = 0_prt;
129
amrex::ParticleReal
x3 = 0_prt;
130
131
amrex::ParticleReal
Q = (3_prt*a*c - powi<2>(b))/(9_prt * powi<2>(a));
132
amrex::ParticleReal
R = (9_prt*a*b*c - 27_prt*powi<2>(a)*d - 2_prt*powi<3>(b))/(54_prt*powi<3>(a));
133
amrex::ParticleReal
discriminant = powi<3>(Q) + powi<2>(R);
134
135
// Define complex variable C
136
Complex
Qc(Q,0_prt);
137
Complex
Rc(R,0_prt);
138
Complex
Dc(discriminant,0_prt);
139
Complex
C =
amrex::pow
(-Rc +
amrex::sqrt
(Dc),1_prt/3_prt);
140
141
// Define a cubic root of unity xi
142
amrex::ParticleReal
xire = -0.5_prt;
143
amrex::ParticleReal
xiim = std::sqrt(3_prt)*0.5_prt;
144
Complex
xi(xire,xiim);
145
146
//Three roots in algebraic form.
147
148
if
(C.
m_real
== 0_prt && C.
m_imag
== 0_prt) {
// Special case of a triple root
149
150
x1 = - b/(3_prt*a);
151
x2 = - b/(3_prt*a);
152
x3 = - b/(3_prt*a);
153
154
}
else
{
155
156
Complex
z1 = Qc/C - C;
157
Complex
z2 = Qc/(xi*C) - xi*C;
158
Complex
z3 = Qc/(powi<2>(xi)*C) - powi<2>(xi)*C;
159
x1 = z2.
m_real
- b/(3_prt*a);
160
x2 = z1.
m_real
- b/(3_prt*a);
161
x3 = z3.
m_real
- b/(3_prt*a);
162
}
163
164
roots = std::make_tuple(x1,x2,x3);
165
return
roots;
166
}
167
168
}
// namespace impactx::diagnostics
169
170
#endif
// COVARIANCE_MATRIX_MATH_H
AMReX_GpuComplex.H
AMReX_Math.H
AMReX_REAL.H
WarnManager.H
Complex
amrex::GpuComplex< amrex::Real > Complex
constant.H
amrex::ParticleReal
amrex_particle_real ParticleReal
ablastr::constant::math::pi
constexpr auto pi
ablastr::warn_manager::WMRecordWarning
void WMRecordWarning(const std::string &topic, const std::string &text, const WarnPriority &priority=WarnPriority::medium)
amrex::Math::powi
constexpr T powi(T x) noexcept
amrex::literals
amrex::pow
__host__ __device__ GpuComplex< T > pow(const GpuComplex< T > &a_z, const T &a_y) noexcept
amrex::sqrt
__host__ __device__ GpuComplex< T > sqrt(const GpuComplex< T > &a_z) noexcept
impactx::diagnostics
Definition
CovarianceMatrixMath.H:25
impactx::diagnostics::CubicRootsAlg
std::tuple< amrex::ParticleReal, amrex::ParticleReal, amrex::ParticleReal > CubicRootsAlg(amrex::ParticleReal a, amrex::ParticleReal b, amrex::ParticleReal c, amrex::ParticleReal d)
Definition
CovarianceMatrixMath.H:115
impactx::diagnostics::CubicRootsTrig
std::tuple< amrex::ParticleReal, amrex::ParticleReal, amrex::ParticleReal > CubicRootsTrig(amrex::ParticleReal a, amrex::ParticleReal b, amrex::ParticleReal c, amrex::ParticleReal d)
Definition
CovarianceMatrixMath.H:43
amrex::GpuComplex
amrex::GpuComplex::m_imag
T m_imag
amrex::GpuComplex::m_real
T m_real
Generated by
1.17.0