ImpactX
Loading...
Searching...
No Matches
CovarianceMatrixMath.H
Go to the documentation of this file.
1/* Copyright 2022-2023 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>
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
25{
26
38 std::tuple<
39 amrex::ParticleReal,
40 amrex::ParticleReal,
41 amrex::ParticleReal
42 >
44 amrex::ParticleReal a,
45 amrex::ParticleReal b,
46 amrex::ParticleReal c,
47 amrex::ParticleReal d
48 )
49 {
50 using namespace amrex::literals;
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; //allow for roundoff error
65 if (discriminant > tol) {
66
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 >
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;
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< amrex::Real > Complex
static constexpr amrex::Real pi
void WMRecordWarning(const std::string &topic, const std::string &text, const WarnPriority &priority=WarnPriority::medium)
constexpr T powi(T x) noexcept
__host__ __device__ GpuComplex< T > pow(const GpuComplex< T > &a_z, const T &a_y) noexcept
__host__ __device__ GpuComplex< T > sqrt(const GpuComplex< T > &a_z) noexcept
Definition CovarianceMatrixMath.H:25
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
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