102 for (
int i = 0; i < N; ++i) {
104 for (
int j = 0; j < N; ++j)
106 r += std::fabs(A[i][j]);
107 const Real l = A[i][i] - r, h = A[i][i] + r;
108 if (i == 0 || l < lo)
110 if (i == 0 || h > hi)
120 for (
int k = 1; k <= N - 2; ++k) {
122 for (
int i = k; i < N; ++i)
123 scale += std::fabs(H[i][k - 1]);
124 if (scale ==
Real(0))
127 for (
int i = k; i < N; ++i) {
128 v[i] = H[i][k - 1] / scale;
131 Real g = std::sqrt(h);
139 for (
int j = k; j < N; ++j) {
141 for (
int i = k; i < N; ++i)
144 for (
int i = k; i < N; ++i)
147 for (
int i = 0; i < N; ++i) {
149 for (
int j = k; j < N; ++j)
152 for (
int j = k; j < N; ++j)
155 H[k][k - 1] = scale * g;
156 for (
int i = k + 1; i < N; ++i)
157 H[i][k - 1] =
Real(0);
162 return sgn >=
Real(0) ? std::fabs(mag) : -std::fabs(mag);
168 if (first || re < lmin)
170 if (first || re > lmax)
172 const Real ai = std::fabs(im);
173 if (first || ai > max_im)
184 int max_iter_per_eig) {
185 constexpr Real kEps = std::numeric_limits<Real>::epsilon();
187 for (
int i = 0; i < N; ++i)
188 for (
int j = (i > 0 ? i - 1 : 0); j < N; ++j)
189 anorm += std::fabs(H[i][j]);
190 if (anorm ==
Real(0)) {
191 lmin = lmax = max_im =
Real(0);
205 for (l = nn; l >= 1; --l) {
206 s = std::fabs(H[l - 1][l - 1]) + std::fabs(H[l][l]);
209 if (std::fabs(H[l][l - 1]) <= kEps * s) {
210 H[l][l - 1] =
Real(0);
219 y = H[nn - 1][nn - 1];
220 w = H[nn][nn - 1] * H[nn - 1][nn];
222 p =
Real(0.5) * (y - x);
224 z = std::sqrt(std::fabs(q));
231 record_eig(x + p, z, lmin, lmax, max_im, first);
232 record_eig(x + p, -z, lmin, lmax, max_im, first);
236 if (its == max_iter_per_eig)
238 if (its == 10 || its == 20) {
240 for (
int i = 0; i <= nn; ++i)
242 s = std::fabs(H[nn][nn - 1]) + std::fabs(H[nn - 1][nn - 2]);
243 y = x =
Real(0.75) * s;
244 w =
Real(-0.4375) * s * s;
248 for (m = nn - 2; m >= l; --m) {
252 p = (r * s - w) / H[m + 1][m] + H[m][m + 1];
253 q = H[m + 1][m + 1] - z - r - s;
255 s = std::fabs(p) + std::fabs(q) + std::fabs(r);
261 const Real u = std::fabs(H[m][m - 1]) * (std::fabs(q) + std::fabs(r));
262 const Real v = std::fabs(p) *
263 (std::fabs(H[m - 1][m - 1]) + std::fabs(z) + std::fabs(H[m + 1][m + 1]));
267 for (
int i = m + 2; i <= nn; ++i) {
268 H[i][i - 2] =
Real(0);
270 H[i][i - 3] =
Real(0);
272 for (
int k = m; k <= nn - 1; ++k) {
276 r = (k != nn - 1) ? H[k + 2][k - 1] :
Real(0);
277 x = std::fabs(p) + std::fabs(q) + std::fabs(r);
289 H[k][k - 1] = -H[k][k - 1];
291 H[k][k - 1] = -s * x;
299 for (
int j = k; j <= nn; ++j) {
300 p = H[k][j] + q * H[k + 1][j];
302 p += r * H[k + 2][j];
303 H[k + 2][j] -= p * z;
305 H[k + 1][j] -= p * y;
308 const int mmin = (nn < k + 3) ? nn : k + 3;
309 for (
int i = l; i <= mmin; ++i) {
310 p = x * H[i][k] + y * H[i][k + 1];
312 p += z * H[i][k + 2];
313 H[i][k + 2] -= p * r;
315 H[i][k + 1] -= p * q;
321 }
while (l < nn - 1);
344 bool* fallback =
nullptr) {
345 static_assert(N >= 1,
"real_eig_minmax: N >= 1");
346 static_assert(N <= 16,
347 "real_eig_minmax: block limited to 16x16 (stack buffer O(N^2) per device "
348 "thread, ~2 KB; beyond that, a dense solver with allocation is more "
349 "appropriate than this path)");
351 if constexpr (N == 1) {
352 b.
lmin = b.lmax = A[0][0];
353 }
else if constexpr (N == 2) {
354 const Real tr2 =
Real(0.5) * (A[0][0] + A[1][1]);
355 const Real disc =
Real(0.25) * (A[0][0] - A[1][1]) * (A[0][0] - A[1][1]) + A[0][1] * A[1][0];
356 if (disc >=
Real(0)) {
357 const Real z = std::sqrt(disc);
361 b.lmin = b.lmax = tr2;
362 b.max_im = std::sqrt(-disc);
366 for (
int i = 0; i < N; ++i)
367 for (
int j = 0; j < N; ++j)
380 *fallback = !b.converged;
397 int max_iter_per_eig = 100) {
413 for (
int i = 0; i < N; ++i)
414 for (
int j = 0; j < N; ++j) {
416 inv[i][j] = (i == j) ?
Real(1) :
Real(0);
418 for (
int col = 0; col < N; ++col) {
420 Real best = std::fabs(M[col][col]);
421 for (
int r = col + 1; r < N; ++r) {
422 const Real v = std::fabs(M[r][col]);
428 if (best < pivot_tol)
431 for (
int j = 0; j < N; ++j) {
433 M[col][j] = M[piv][j];
436 inv[col][j] = inv[piv][j];
439 const Real invd =
Real(1) / M[col][col];
440 for (
int j = 0; j < N; ++j) {
444 for (
int r = 0; r < N; ++r) {
447 const Real f = M[r][col];
449 for (
int j = 0; j < N; ++j) {
450 M[r][j] -= f * M[col][j];
451 inv[r][j] -= f * inv[col][j];
462 for (
int i = 0; i < N; ++i) {
464 for (
int j = 0; j < N; ++j)
465 r += std::fabs(A[i][j]);
491 int max_iter = 80,
Real tol =
Real(1e-13)) {
492 static_assert(N >= 1 && N <= 16,
"roe_abs_apply: 1 <= N <= 16");
495 Real S[N][N], Sinv[N][N];
496 for (
int i = 0; i < N; ++i)
497 for (
int j = 0; j < N; ++j)
499 bool converged =
false;
500 for (
int it = 0; it < max_iter; ++it) {
506 mu = std::sqrt(nsi / ns);
509 for (
int i = 0; i < N; ++i)
510 for (
int j = 0; j < N; ++j) {
511 const Real snext = a * S[i][j] + b * Sinv[i][j];
512 const Real d = snext - S[i][j];
514 nrm += snext * snext;
517 if (nrm >
Real(0) && diff <= tol * tol * nrm) {
526 for (
int i = 0; i < N; ++i) {
528 for (
int j = 0; j < N; ++j)
529 s += S[i][j] * dU[j];
532 for (
int i = 0; i < N; ++i) {
534 for (
int j = 0; j < N; ++j)
535 s += A[i][j] * SdU[j];
POPS_HD bool mat_inverse(const Real(&A)[N][N], Real(&inv)[N][N], Real pivot_tol=Real(1e-300))
Inverse of a dense N x N matrix by Gauss-Jordan elimination with partial pivoting,...
Definition dense_eig.hpp:410
POPS_HD Real hqr_copysign(Real mag, Real sgn)
Definition dense_eig.hpp:161
POPS_HD Real mat_norm_inf(const Real(&A)[N][N])
Max absolute row sum (infinity norm) of a dense N x N matrix.
Definition dense_eig.hpp:460
POPS_HD bool hqr_minmax(Real(&H)[N][N], Real &lmin, Real &lmax, Real &max_im, int max_iter_per_eig)
QR iteration with implicit Francis double shift on a Hessenberg matrix (EISPACK/hqr formulation,...
Definition dense_eig.hpp:183
POPS_HD void hessenberg_reduce(Real(&H)[N][N])
Upper Hessenberg reduction by Householder reflections, IN PLACE, without accumulating the transformat...
Definition dense_eig.hpp:118
POPS_HD void record_eig(Real re, Real im, Real &lmin, Real &lmax, Real &max_im, bool &first)
Accumulate an eigenvalue (re, im) into the current extremes.
Definition dense_eig.hpp:167
POPS_HD void gershgorin_bounds(const Real(&A)[N][N], Real &lo, Real &hi)
Gershgorin bound on the REAL PARTS: every lambda of the spectrum satisfies lo <= Re(lambda) <= hi (di...
Definition dense_eig.hpp:101
Definition amr_hierarchy.hpp:29
Spectrum
Tri-state classification of a small block's spectrum (ADC-276), returned by pops::real_spectrum.
Definition dense_eig.hpp:93
POPS_HD bool roe_abs_apply(const Real(&A)[N][N], const Real(&dU)[N], Real(&out)[N], int max_iter=80, Real tol=Real(1e-13))
Roe matrix-absolute-value applied to a state jump: out = |A| dU, with |A| the SPECTRAL absolute value...
Definition dense_eig.hpp:490
double Real
Definition types.hpp:30
POPS_HD Spectrum real_spectrum(const Real(&A)[N][N], Real im_tol=Real(1e-5), int max_iter_per_eig=100)
Classify the spectrum of a small dense block A as kReal / kComplexPair / kUnknown (ADC-276): a GENERI...
Definition dense_eig.hpp:396
POPS_HD EigBounds real_eig_minmax(const Real(&A)[N][N], int max_iter_per_eig=100, bool *fallback=nullptr)
Extremes of the REAL PARTS of the spectrum of a small dense block A, plus the largest |Im| encountere...
Definition dense_eig.hpp:343
Result of real_eig_minmax: real-part extremes + diagnostic.
Definition dense_eig.hpp:53
Real lmax
largest real part (or Gershgorin upper bound if !converged)
Definition dense_eig.hpp:55
POPS_HD bool all_real(Real im_tol=Real(1e-5)) const
REAL-SPECTRUM PREDICATE (ADC-276).
Definition dense_eig.hpp:76
Real lmin
smallest real part (or Gershgorin lower bound if !converged)
Definition dense_eig.hpp:54
bool converged
false -> Gershgorin fallback (valid external bound, NOT the spectrum)
Definition dense_eig.hpp:59
POPS_HD bool has_complex_pair(Real im_tol=Real(1e-5)) const
Complement of all_real RESTRICTED to converged blocks: true iff the spectrum was computed AND carries...
Definition dense_eig.hpp:84
Real max_im
largest |Im(lambda)| encountered (0 = real spectrum: hyperbolic).
Definition dense_eig.hpp:56
Base scalar types and the POPS_HD macro (host+device portability).
#define POPS_HD
Definition types.hpp:25