mirror of
https://github.com/paboyle/Grid.git
synced 2026-07-18 16:13:28 +01:00
Adding verify() routines to gamma5BlockLanczos
This commit is contained in:
@@ -137,6 +137,137 @@ public:
|
|||||||
computeRitzPairs(nSteps, Nstop);
|
computeRitzPairs(nSteps, Nstop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the block Lanczos decomposition after operator() has run.
|
||||||
|
*
|
||||||
|
* Checks the three-term recurrence
|
||||||
|
*
|
||||||
|
* D_W Q_k = Q_{k-1} C_k + Q_k A_k + Q_{k+1} B_{k+1}
|
||||||
|
*
|
||||||
|
* for each completed step k=1..m, plus γ5-orthonormality and
|
||||||
|
* off-diagonal γ5-orthogonality between all Krylov blocks.
|
||||||
|
*
|
||||||
|
* Prints:
|
||||||
|
* - T_m (block tridiagonal projected matrix, 2m × 2m)
|
||||||
|
* - A_k, B_k, C_k, G_k for each step
|
||||||
|
* - max |G_computed[k] - G_stored[k]| (γ5-Gram diagonal consistency)
|
||||||
|
* - max |Q_i†γ5 Q_j| for i≠j (inter-block γ5-orthogonality)
|
||||||
|
* - per-column recurrence residual || D_W q - Q_{k-1}C - Q_k A - Q_{k+1}B ||
|
||||||
|
*/
|
||||||
|
void verify(const std::string& label = "")
|
||||||
|
{
|
||||||
|
int m = nSteps;
|
||||||
|
if (m == 0) {
|
||||||
|
std::cout << GridLogMessage
|
||||||
|
<< "Gamma5BlockLanczos::verify: no steps completed." << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << GridLogMessage
|
||||||
|
<< "======== Gamma5BlockLanczos::verify [" << label << "] ========" << std::endl;
|
||||||
|
std::cout << GridLogMessage
|
||||||
|
<< " m = " << m << " completed steps, basis vectors = " << basis.size() << std::endl;
|
||||||
|
|
||||||
|
// ---- Assemble and print T_m ----
|
||||||
|
int dim = 2 * m;
|
||||||
|
CMat Tm = CMat::Zero(dim, dim);
|
||||||
|
for (int k = 0; k < m; k++) {
|
||||||
|
Tm.block(2*k, 2*k, 2, 2) = A_blocks[k];
|
||||||
|
if (k < m - 1) {
|
||||||
|
Tm.block(2*k+2, 2*k, 2, 2) = B_blocks[k];
|
||||||
|
Tm.block(2*k, 2*k+2, 2, 2) = C_blocks[k+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << GridLogMessage << "T_m (" << dim << " x " << dim << "):" << std::endl;
|
||||||
|
for (int i = 0; i < dim; i++) {
|
||||||
|
for (int j = 0; j < dim; j++)
|
||||||
|
std::cout << " " << std::setprecision(6) << std::setw(16) << Tm(i, j);
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Print per-step coefficient blocks ----
|
||||||
|
for (int k = 0; k < m; k++) {
|
||||||
|
std::cout << GridLogMessage << " A[" << k << "] =\n" << A_blocks[k] << std::endl;
|
||||||
|
std::cout << GridLogMessage << " B[" << k << "] =\n" << B_blocks[k] << std::endl;
|
||||||
|
std::cout << GridLogMessage << " C[" << k << "] =\n" << C_blocks[k] << std::endl;
|
||||||
|
std::cout << GridLogMessage << " G[" << k << "] =\n" << G_blocks[k] << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << GridLogMessage << " G[" << m << "] =\n" << G_blocks[m] << std::endl;
|
||||||
|
|
||||||
|
// ---- Check γ5-Gram consistency: compare stored G_blocks[k] with recomputed Q_k†γ5Q_k ----
|
||||||
|
// basis[2k..2k+1] = code block k (= paper Q_{k+1}); G_blocks[k] = paper G_{k+1}.
|
||||||
|
RealD maxGramErr = 0.0;
|
||||||
|
for (int k = 0; k <= m; k++) {
|
||||||
|
CMat2 Gcomp = gramMatrix(basis[2*k], basis[2*k + 1]);
|
||||||
|
CMat2 Gerr = Gcomp - G_blocks[k];
|
||||||
|
RealD err = Gerr.cwiseAbs().maxCoeff();
|
||||||
|
maxGramErr = std::max(maxGramErr, err);
|
||||||
|
std::cout << GridLogMessage
|
||||||
|
<< " |G_computed[" << k << "] - G_stored[" << k << "]|_max = " << err << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << GridLogMessage
|
||||||
|
<< " max γ5-Gram diagonal error = " << maxGramErr << std::endl;
|
||||||
|
|
||||||
|
// ---- Check γ5-orthogonality between different blocks: Q_i†γ5 Q_j ≈ 0 for i≠j ----
|
||||||
|
RealD maxOffDiag = 0.0;
|
||||||
|
for (int i = 0; i <= m; i++) {
|
||||||
|
for (int j = 0; j <= m; j++) {
|
||||||
|
if (i == j) continue;
|
||||||
|
CMat2 Mij = g5InnerBlock(basis[2*i], basis[2*i+1], basis[2*j], basis[2*j+1]);
|
||||||
|
RealD err = Mij.cwiseAbs().maxCoeff();
|
||||||
|
maxOffDiag = std::max(maxOffDiag, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << GridLogMessage
|
||||||
|
<< " max |Q_i†γ5 Q_j| (i≠j, should be ~0) = " << maxOffDiag << std::endl;
|
||||||
|
|
||||||
|
// ---- Check three-term recurrence for each code block k=0..m-1 ----
|
||||||
|
// Recurrence (code indices):
|
||||||
|
// D_W basis[2k..2k+1] = basis[2k..2k+1] * A_blocks[k]
|
||||||
|
// + basis[2(k-1)..] * C_blocks[k] (k > 0; C_blocks[0] = 0)
|
||||||
|
// + basis[2(k+1)..] * B_blocks[k]
|
||||||
|
RealD maxRecErr = 0.0;
|
||||||
|
Field p1(Grid_), p2(Grid_), r1(Grid_), r2(Grid_);
|
||||||
|
for (int k = 0; k < m; k++) {
|
||||||
|
const Field& q1 = basis[2*k];
|
||||||
|
const Field& q2 = basis[2*k + 1];
|
||||||
|
const Field& qn1 = basis[2*(k+1)];
|
||||||
|
const Field& qn2 = basis[2*(k+1) + 1];
|
||||||
|
|
||||||
|
Linop.Op(q1, p1);
|
||||||
|
Linop.Op(q2, p2);
|
||||||
|
|
||||||
|
// subtract Q_k A_k
|
||||||
|
r1 = p1 - q1 * A_blocks[k](0,0) - q2 * A_blocks[k](1,0);
|
||||||
|
r2 = p2 - q1 * A_blocks[k](0,1) - q2 * A_blocks[k](1,1);
|
||||||
|
|
||||||
|
// subtract Q_{k-1} C_k (C_blocks[0] = 0, so k=0 is automatically fine)
|
||||||
|
if (k > 0) {
|
||||||
|
const Field& qp1 = basis[2*(k-1)];
|
||||||
|
const Field& qp2 = basis[2*(k-1) + 1];
|
||||||
|
r1 -= qp1 * C_blocks[k](0,0) + qp2 * C_blocks[k](1,0);
|
||||||
|
r2 -= qp1 * C_blocks[k](0,1) + qp2 * C_blocks[k](1,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// subtract Q_{k+1} B_{k+1} (= basis[2(k+1)..] * B_blocks[k])
|
||||||
|
r1 -= qn1 * B_blocks[k](0,0) + qn2 * B_blocks[k](1,0);
|
||||||
|
r2 -= qn1 * B_blocks[k](0,1) + qn2 * B_blocks[k](1,1);
|
||||||
|
|
||||||
|
RealD dev1 = std::sqrt(norm2(r1));
|
||||||
|
RealD dev2 = std::sqrt(norm2(r2));
|
||||||
|
std::cout << GridLogMessage
|
||||||
|
<< " recurrence k=" << k
|
||||||
|
<< ": || D_W q[2k] - ... || = " << dev1
|
||||||
|
<< " || D_W q[2k+1] - ... || = " << dev2 << std::endl;
|
||||||
|
maxRecErr = std::max({maxRecErr, dev1, dev2});
|
||||||
|
}
|
||||||
|
std::cout << GridLogMessage
|
||||||
|
<< " max recurrence deviation = " << maxRecErr << std::endl;
|
||||||
|
|
||||||
|
std::cout << GridLogMessage
|
||||||
|
<< "======== end Gamma5BlockLanczos::verify ========" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// One Lanczos step. On success pushes Q_{step+2} and returns true.
|
// One Lanczos step. On success pushes Q_{step+2} and returns true.
|
||||||
bool lanczosStep(int step, bool reorthog)
|
bool lanczosStep(int step, bool reorthog)
|
||||||
|
|||||||
Reference in New Issue
Block a user