mirror of
https://github.com/paboyle/Grid.git
synced 2026-07-18 08:03:27 +01:00
Finally Block Harmonic(?) KS working
This commit is contained in:
@@ -34,65 +34,44 @@ See the full license in the file "LICENSE" in the top level distribution directo
|
|||||||
NAMESPACE_BEGIN(Grid);
|
NAMESPACE_BEGIN(Grid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Block harmonic restarted Krylov-Schur eigensolver.
|
* Block shift-targeted Krylov-Schur eigensolver.
|
||||||
*
|
*
|
||||||
* Harmonic Ritz values
|
* Algorithm
|
||||||
* --------------------
|
* ---------
|
||||||
* Standard Ritz values of A in a Krylov space K_m minimise the residual
|
* Uses a block Arnoldi factorisation:
|
||||||
* in a Galerkin sense; they are good approximations to eigenvalues at the
|
|
||||||
* *exterior* of the spectrum. For eigenvalues *near* a target shift σ
|
|
||||||
* (e.g. the smallest eigenvalues when σ=0) harmonic Ritz values are
|
|
||||||
* better-suited: they are obtained by a Petrov-Galerkin condition that
|
|
||||||
* requires the residual to be orthogonal to (A-σI)K_m instead of K_m.
|
|
||||||
*
|
|
||||||
* Given the block Arnoldi factorisation
|
|
||||||
*
|
*
|
||||||
* A V = V H + F B^dag (1)
|
* A V = V H + F B^dag (1)
|
||||||
*
|
*
|
||||||
* with V orthonormal (Nm columns), H the Nm² block
|
* with V orthonormal (Nm columns), H the Nm×Nm block upper-Hessenberg
|
||||||
* upper-Hessenberg Rayleigh quotient, F the Nblock residual vectors and B
|
* Rayleigh quotient, F the Nblock residual vectors and B the Nm×Nblock
|
||||||
* the Nm×Nblock coupling matrix, the harmonic Rayleigh quotient
|
* coupling matrix.
|
||||||
* relative to shift σ is
|
|
||||||
*
|
|
||||||
* Hhat = H + (H - σI)^{-H} B B^H (2)
|
|
||||||
*
|
|
||||||
* Derivation: the harmonic Ritz condition (A-σI)Vy ⊥ (A-σI)V leads to
|
|
||||||
*
|
|
||||||
* [ (H-σI)^H (H-σI) + B B^H ] y = μ (H-σI)^H y
|
|
||||||
*
|
|
||||||
* Left-multiplying by (H-σI)^{-H} and setting θ = μ + σ gives the
|
|
||||||
* standard eigenvalue problem Hhat y = θ y with Hhat as in (2).
|
|
||||||
*
|
|
||||||
* The harmonic Ritz values θ_j are eigenvalues of Hhat; among these,
|
|
||||||
* the ones closest to σ (smallest |θ_j - σ|) are the best approximations
|
|
||||||
* to the eigenvalues of A near σ.
|
|
||||||
*
|
*
|
||||||
* Thick restart
|
* Thick restart
|
||||||
* -------------
|
* -------------
|
||||||
* The Schur decomposition Hhat = Q^dag S Q is computed and the
|
* To target eigenvalues near shift σ, the Schur decomposition is computed
|
||||||
* leading Nk*Nblock Schur values (sorted by the RitzFilter) are kept.
|
* for the shifted Rayleigh quotient:
|
||||||
* The same unitary rotation Q is applied to both the Krylov basis and
|
|
||||||
* to the *original* Rayleigh quotient H (not Hhat) for the restart:
|
|
||||||
*
|
*
|
||||||
* V_new = V Q^dag [first Nk*Nblock columns]
|
* (H - σI) = Q^dag S Q (2)
|
||||||
* H_new = Q H Q^dag [truncated Nk*Nblock × Nk*Nblock]
|
|
||||||
* B_new = Q B [truncated Nk*Nblock × Nblock]
|
|
||||||
*
|
*
|
||||||
* Block Arnoldi then resumes from block Nk, restoring H to full size
|
* Sorting the Schur values of (H - σI) by smallest |S(i,i)| = |λ - σ| and
|
||||||
* as new columns are appended.
|
* retaining the leading Nk is equivalent to selecting the Ritz values of H
|
||||||
|
* closest to σ. Since Q diagonalises H - σI (and hence H itself), the
|
||||||
|
* rotated Rayleigh quotient is exactly upper triangular:
|
||||||
|
*
|
||||||
|
* H_new = Q H Q^dag = S + σI (upper triangular) (3)
|
||||||
|
*
|
||||||
|
* Truncation to Nk is therefore exact: the off-diagonal coupling block
|
||||||
|
* H_new[Nk:, :Nk] = 0 by triangularity. The Krylov-Schur relation after
|
||||||
|
* restart is exact and block Arnoldi resumes cleanly from F.
|
||||||
*
|
*
|
||||||
* Convergence
|
* Convergence
|
||||||
* -----------
|
* -----------
|
||||||
* For a harmonic Ritz pair (θ, y) the true Ritz residual bound is
|
* Convergence is declared when || B^H y_k || < Tolerance * approxLambdaMax
|
||||||
*
|
* for each Ritz pair (λ_k, y_k) of the truncated H.
|
||||||
* || (A - θI) V y || ≤ || B^H y ||
|
|
||||||
*
|
|
||||||
* (same as for standard Ritz, because B captures the full coupling).
|
|
||||||
* Convergence is declared when || B^H y || < Tolerance * approxLambdaMax.
|
|
||||||
*
|
*
|
||||||
* Parameters
|
* Parameters
|
||||||
* ----------
|
* ----------
|
||||||
* shift : target shift σ (default 0.0)
|
* shift : target shift σ (default 0.0); Schur values sorted by |λ - σ|
|
||||||
* Nblock : block size p
|
* Nblock : block size p
|
||||||
* Nm : total Krylov dimension (must be divisible by Nblock)
|
* Nm : total Krylov dimension (must be divisible by Nblock)
|
||||||
* Nk : total vectors to retain after each restart (must be divisible by Nblock, Nk < Nm)
|
* Nk : total vectors to retain after each restart (must be divisible by Nblock, Nk < Nm)
|
||||||
@@ -205,70 +184,38 @@ public:
|
|||||||
verify(lbl);
|
verify(lbl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Form harmonic Rayleigh quotient ----
|
// ---- Schur decompose (H - σI) to select Schur vectors closest to σ ----
|
||||||
// Hhat = H + (H - σI)^{-H} * B * B^H
|
// Sorting the Schur values of (H - σI) by |S(i,i)| = |λ - σ| gives the
|
||||||
CMat Hhat = harmonicRayleigh(H, B, N);
|
// Ritz values of H nearest the target shift without any matrix inversion.
|
||||||
|
// Because Q diagonalises (H - σI), it also diagonalises H:
|
||||||
// ---- Schur decompose Hhat ----
|
// H_new = Q H Q^dag = S + σI (upper triangular)
|
||||||
ComplexSchurDecomposition schur(Hhat, false, ritzFilter);
|
// Truncation is therefore exact.
|
||||||
|
CMat Hshift = H - shift * CMat::Identity(N, N);
|
||||||
|
ComplexSchurDecomposition schur(Hshift, false, ritzFilter);
|
||||||
schur.schurReorder(Nk);
|
schur.schurReorder(Nk);
|
||||||
|
|
||||||
std::cout << GridLogMessage
|
std::cout << GridLogMessage
|
||||||
<< "HarmonicBlockKrylovSchur: harmonic Ritz values (first Nk):" << std::endl;
|
<< "HarmonicBlockKrylovSchur: Ritz values nearest shift (first Nk):" << std::endl;
|
||||||
CMat S = schur.getMatrixS();
|
CMat S = schur.getMatrixS();
|
||||||
for (int i = 0; i < Nk; i++)
|
for (int i = 0; i < Nk; i++)
|
||||||
std::cout << GridLogMessage << " [" << i << "] " << S(i, i) << std::endl;
|
std::cout << GridLogMessage << " [" << i << "] " << S(i, i) + shift << std::endl;
|
||||||
|
|
||||||
CMat Q = schur.getMatrixQ();
|
CMat Q = schur.getMatrixQ();
|
||||||
CMat Qt = Q.adjoint();
|
CMat Qt = Q.adjoint();
|
||||||
|
|
||||||
// ---- Rotate Krylov basis using Q from Hhat ----
|
// ---- Rotate Krylov basis ----
|
||||||
std::vector<Field> basis2;
|
std::vector<Field> basis2;
|
||||||
constructUR(basis2, basis, Qt, N);
|
constructUR(basis2, basis, Qt, N);
|
||||||
basis = basis2;
|
basis = basis2;
|
||||||
|
|
||||||
// ---- Update H and B (rotate H, not Hhat) ----
|
// ---- Update H and B ----
|
||||||
H = Q * H * Qt;
|
// H_new = S + σI is upper triangular; off-diagonal block H_new[Nk:,:Nk] = 0
|
||||||
|
H = S + shift * CMat::Identity(N, N);
|
||||||
B = Q * B;
|
B = Q * B;
|
||||||
|
|
||||||
// ---- Truncate to Nk ----
|
// ---- Truncate to Nk (exact: H upper triangular) ----
|
||||||
int Nkeep = Nk;
|
int Nkeep = Nk;
|
||||||
|
|
||||||
// ---- Option B: corrected restart starting block -------------------------
|
|
||||||
//
|
|
||||||
// In standard Krylov-Schur, Q diagonalises H itself, so Q H Q^H = S is
|
|
||||||
// upper triangular and the off-diagonal coupling block H_dk = S[Nkeep:,:Nkeep] = 0.
|
|
||||||
// Truncation is therefore exact.
|
|
||||||
//
|
|
||||||
// Here Q diagonalises Hhat (not H), so H_new = Q H Q^H is generally dense.
|
|
||||||
// The off-diagonal block
|
|
||||||
//
|
|
||||||
// H_dk = H_new[Nkeep:, :Nkeep] (size (N-Nkeep) x Nkeep)
|
|
||||||
//
|
|
||||||
// is non-zero, and the true KS relation after truncation is:
|
|
||||||
//
|
|
||||||
// A V_k = V_k H_k + V_disc H_dk + F B_k^H
|
|
||||||
//
|
|
||||||
// If we restart from F only, the V_disc H_dk term is lost.
|
|
||||||
//
|
|
||||||
// Fix: include the V_disc coupling in the new starting block:
|
|
||||||
//
|
|
||||||
// G[t] = F[t] + sum_{s=Nkeep}^{N-1} basis[s] * H(s, t), t = 0..Nblock-1
|
|
||||||
//
|
|
||||||
// G[:,t] is the t-th column of (V_disc H_dk + F B_k^H) restricted to the
|
|
||||||
// first Nblock columns of H_dk. Since F ⊥ V_k and V_disc ⊥ V_k, G is
|
|
||||||
// automatically orthogonal to the retained subspace.
|
|
||||||
//
|
|
||||||
// This must be computed BEFORE basis[Nkeep:] and H[Nkeep:, :] are discarded.
|
|
||||||
|
|
||||||
std::vector<Field> G(Nblock, Field(Grid_));
|
|
||||||
for (int t = 0; t < Nblock; t++) {
|
|
||||||
G[t] = F[t];
|
|
||||||
for (int s = Nkeep; s < N; s++)
|
|
||||||
G[t] += basis[s] * H(s, t);
|
|
||||||
}
|
|
||||||
blockQR(G); // orthonormalise within G (G is already ⊥ to basis[0:Nkeep])
|
|
||||||
|
|
||||||
CMat Htmp = H(Eigen::seqN(0, Nkeep), Eigen::seqN(0, Nkeep));
|
CMat Htmp = H(Eigen::seqN(0, Nkeep), Eigen::seqN(0, Nkeep));
|
||||||
H = CMat::Zero(N, N);
|
H = CMat::Zero(N, N);
|
||||||
H(Eigen::seqN(0, Nkeep), Eigen::seqN(0, Nkeep)) = Htmp;
|
H(Eigen::seqN(0, Nkeep), Eigen::seqN(0, Nkeep)) = Htmp;
|
||||||
@@ -284,10 +231,8 @@ public:
|
|||||||
std::cout << GridLogMessage
|
std::cout << GridLogMessage
|
||||||
<< "HarmonicBlockKrylovSchur: beta_k = " << beta_k << std::endl;
|
<< "HarmonicBlockKrylovSchur: beta_k = " << beta_k << std::endl;
|
||||||
|
|
||||||
// Use corrected starting block G (not bare F).
|
// Restart from F (exact: no discarded-basis correction needed)
|
||||||
// G encodes the coupling from the discarded basis vectors V_disc through
|
startBlock = F;
|
||||||
// H_dk[:,0:Nblock], restoring the exact KS relation to first order.
|
|
||||||
startBlock = G;
|
|
||||||
|
|
||||||
if (doVerify) {
|
if (doVerify) {
|
||||||
std::string lbl = "iter " + std::to_string(iter) + " after restart+truncation";
|
std::string lbl = "iter " + std::to_string(iter) + " after restart+truncation";
|
||||||
@@ -327,8 +272,7 @@ public:
|
|||||||
* A V = V H + F B^dag (KS)
|
* A V = V H + F B^dag (KS)
|
||||||
*
|
*
|
||||||
* by explicit operator applications. H here is the standard Rayleigh
|
* by explicit operator applications. H here is the standard Rayleigh
|
||||||
* quotient (not Hhat), so the KS relation is the same as for
|
* quotient, so the KS relation is the same as for BlockKrylovSchur.
|
||||||
* BlockKrylovSchur.
|
|
||||||
*
|
*
|
||||||
* Prints:
|
* Prints:
|
||||||
* - H (current Rayleigh quotient, nBasis × nBasis)
|
* - H (current Rayleigh quotient, nBasis × nBasis)
|
||||||
@@ -445,32 +389,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
|
||||||
// Harmonic Rayleigh quotient
|
|
||||||
//--------------------------------------------------------------------
|
|
||||||
/**
|
|
||||||
* Forms the harmonic Rayleigh quotient relative to shift σ:
|
|
||||||
*
|
|
||||||
* Hhat = H + (H - σI)^{-H} * B * B^H
|
|
||||||
*
|
|
||||||
* where H is the N×N block-Hessenberg, B is the N×Nblock coupling matrix.
|
|
||||||
*
|
|
||||||
* The N×N solve (H - σI)^H X = B B^H is done via Eigen's LU
|
|
||||||
* factorisation. If H - σI is (nearly) singular the result is
|
|
||||||
* ill-conditioned; in that case σ should be perturbed slightly.
|
|
||||||
*/
|
|
||||||
CMat harmonicRayleigh(const CMat& H_, const CMat& B_, int N)
|
|
||||||
{
|
|
||||||
CMat K = H_ - shift * CMat::Identity(N, N);
|
|
||||||
CMat KH = K.adjoint(); // (H - σI)^H
|
|
||||||
|
|
||||||
// Solve KH * X = B B^H → X = KH^{-1} B B^H = (H-σI)^{-H} B B^H
|
|
||||||
CMat BBH = B_ * B_.adjoint(); // N × N
|
|
||||||
CMat X = KH.lu().solve(BBH); // N × N
|
|
||||||
|
|
||||||
return H_ + X;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// Block Arnoldi iteration
|
// Block Arnoldi iteration
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
@@ -491,24 +409,15 @@ private:
|
|||||||
} else {
|
} else {
|
||||||
// Append the new starting block to the retained basis.
|
// Append the new starting block to the retained basis.
|
||||||
//
|
//
|
||||||
// Standard KS (startBlock = F):
|
// The exact truncated KS relation is A V_k = V_k H_k + F B_k^dag,
|
||||||
// The exact truncated relation is A V_k = V_k H_k + F B_k^dag,
|
|
||||||
// so the coupling rows are H[Nkeep+t, j] = conj(B_k[j,t]).
|
// so the coupling rows are H[Nkeep+t, j] = conj(B_k[j,t]).
|
||||||
//
|
// Since H_new = S + σI is upper triangular, the off-diagonal block
|
||||||
// Harmonic KS Option B (startBlock = G, where G = F + V_disc H_dk[:,0:Nblock]):
|
// H_new[Nkeep:, :Nkeep] = 0 and the restart from F is exact.
|
||||||
// The exact coupling rows are H[Nkeep+t, j] = <G[t], A V_k[:,j]>,
|
|
||||||
// which differs from conj(B_k[j,t]) because G ≠ F.
|
|
||||||
// For a Hermitian operator these preset rows are overwritten by the
|
|
||||||
// Hermitian symmetry fill inside blockArnoldiStep (via explicit inner
|
|
||||||
// products), so the approximate preset below does no harm.
|
|
||||||
// For a non-Hermitian operator the preset is approximate; a more
|
|
||||||
// expensive fix would compute <G[t], A V_k[:,j]> explicitly here.
|
|
||||||
int Nkeep = startIdx * Nblock;
|
int Nkeep = startIdx * Nblock;
|
||||||
for (auto& v : startBlock) basis.push_back(v);
|
for (auto& v : startBlock) basis.push_back(v);
|
||||||
|
|
||||||
// Fill restart coupling rows into H (exact for standard KS; approximate
|
// Fill restart coupling rows into H (exact: H_new is upper triangular,
|
||||||
// for harmonic KS with Option-B starting block, but overwritten by
|
// so B encodes the only non-zero coupling to the new block).
|
||||||
// Hermitian symmetry fill for Hermitian operators).
|
|
||||||
for (int t = 0; t < Nblock; t++)
|
for (int t = 0; t < Nblock; t++)
|
||||||
for (int j = 0; j < Nkeep; j++)
|
for (int j = 0; j < Nkeep; j++)
|
||||||
H(Nkeep + t, j) = std::conj(B(j, t));
|
H(Nkeep + t, j) = std::conj(B(j, t));
|
||||||
@@ -560,10 +469,6 @@ private:
|
|||||||
for (int s = 0; s < Nblock; s++)
|
for (int s = 0; s < Nblock; s++)
|
||||||
B(kBase + t, s) = std::conj(R(s, t)); // B_block = R^H
|
B(kBase + t, s) = std::conj(R(s, t)); // B_block = R^H
|
||||||
beta_k = R.norm();
|
beta_k = R.norm();
|
||||||
// Hermitian symmetry fill for last block (same as non-last path below)
|
|
||||||
for (int t = 0; t < Nblock; t++)
|
|
||||||
for (int j = 0; j < kBase; j++)
|
|
||||||
H(kBase + t, j) = std::conj(H(j, kBase + t));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,23 +483,6 @@ private:
|
|||||||
for (int t = 0; t < Nblock; t++)
|
for (int t = 0; t < Nblock; t++)
|
||||||
basis.push_back(F[t]);
|
basis.push_back(F[t]);
|
||||||
|
|
||||||
// Hermitian symmetry fill: H[kBase+t, j] = conj(H[j, kBase+t]) for j < kBase.
|
|
||||||
//
|
|
||||||
// In a fresh block Arnoldi the Krylov structure forces H[kBase+t, j] = 0 for
|
|
||||||
// j < kBase-Nblock (sub-subdiagonal), so this is a no-op.
|
|
||||||
//
|
|
||||||
// After a non-Schur restart (e.g. harmonic restart where H_new = Q H Q^dag is
|
|
||||||
// a full matrix), A v_k_j for j < Nkeep has components in ALL new extended
|
|
||||||
// vectors, making these elements non-zero. The Arnoldi step fills column
|
|
||||||
// kBase+t (H[j, kBase+t] for j < prevN) via inner products, but never fills
|
|
||||||
// the corresponding row. For a Hermitian operator the two are related by
|
|
||||||
// H[kBase+t, j] = <basis[kBase+t] | A basis[j]>
|
|
||||||
// = conj(<basis[j] | A basis[kBase+t]>) = conj(H[j, kBase+t])
|
|
||||||
// Filling these ensures H = H^dag and fixes the M != H discrepancy that
|
|
||||||
// corrupts subsequent Arnoldi steps after a harmonic restart.
|
|
||||||
for (int t = 0; t < Nblock; t++)
|
|
||||||
for (int j = 0; j < kBase; j++)
|
|
||||||
H(kBase + t, j) = std::conj(H(j, kBase + t));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ struct LanczosParameters: Serializable {
|
|||||||
Integer, maxIter,
|
Integer, maxIter,
|
||||||
Integer, Nblock,
|
Integer, Nblock,
|
||||||
Integer, verify,
|
Integer, verify,
|
||||||
|
RealD, shift ,
|
||||||
RealD, resid,
|
RealD, resid,
|
||||||
RealD, ChebyLow,
|
RealD, ChebyLow,
|
||||||
RealD, ChebyHigh,
|
RealD, ChebyHigh,
|
||||||
@@ -117,12 +118,9 @@ public:
|
|||||||
InvertNonHermitianLinearOperator(Matrix &Mat,RealD stp=1e-8): _Mat(Mat),_stp(stp){};
|
InvertNonHermitianLinearOperator(Matrix &Mat,RealD stp=1e-8): _Mat(Mat),_stp(stp){};
|
||||||
// Support for coarsening to a multigrid
|
// Support for coarsening to a multigrid
|
||||||
void OpDiag (const Field &in, Field &out) {
|
void OpDiag (const Field &in, Field &out) {
|
||||||
// _Mat.Mdiag(in,out);
|
|
||||||
// out = out + shift*in;
|
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
void OpDir (const Field &in, Field &out,int dir,int disp) {
|
void OpDir (const Field &in, Field &out,int dir,int disp) {
|
||||||
// _Mat.Mdir(in,out,dir,disp);
|
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
void OpDirAll (const Field &in, std::vector<Field> &out){
|
void OpDirAll (const Field &in, std::vector<Field> &out){
|
||||||
@@ -131,11 +129,6 @@ public:
|
|||||||
};
|
};
|
||||||
void Op (const Field &in, Field &out){
|
void Op (const Field &in, Field &out){
|
||||||
Field tmp(in.Grid());
|
Field tmp(in.Grid());
|
||||||
// _Mat.M(in,out);
|
|
||||||
// RealD mass=-shift;
|
|
||||||
// WilsonCloverFermionD Dw(Umu, Grid, RBGrid, mass, csw_r, csw_t);
|
|
||||||
// NonHermitianLinearOperator<Matrix,Field> HermOp(_Mat);
|
|
||||||
// BiCGSTAB<Field> CG(_stp,10000);
|
|
||||||
_Mat.Mdag(in,tmp);
|
_Mat.Mdag(in,tmp);
|
||||||
MdagMLinearOperator<Matrix,Field> HermOp(_Mat);
|
MdagMLinearOperator<Matrix,Field> HermOp(_Mat);
|
||||||
ConjugateGradient<Field> CG(_stp,10000);
|
ConjugateGradient<Field> CG(_stp,10000);
|
||||||
@@ -341,12 +334,7 @@ int main (int argc, char ** argv)
|
|||||||
|
|
||||||
// Run KrylovSchur and Arnoldi on a Hermitian matrix
|
// Run KrylovSchur and Arnoldi on a Hermitian matrix
|
||||||
std::cout << GridLogMessage << "Running Krylov Schur" << std::endl;
|
std::cout << GridLogMessage << "Running Krylov Schur" << std::endl;
|
||||||
// KrylovSchur KrySchur (Dsq, FGrid, 1e-8, EvalNormLarge);
|
RealD shift=LanParams.shift;
|
||||||
// KrylovSchur KrySchur (Dsq, FGrid, 1e-8,EvalImNormSmall);
|
|
||||||
// KrySchur(src, maxIter, Nm, Nk, Nstop);
|
|
||||||
// KrylovSchur KrySchur (HermOp2, UGrid, resid,EvalNormSmall);
|
|
||||||
// Hacked, really EvalImagSmall
|
|
||||||
RealD shift=1.5;
|
|
||||||
#if 0
|
#if 0
|
||||||
KrylovSchur KrySchur (Dwilson, UGrid, resid,EvalImNormSmall);
|
KrylovSchur KrySchur (Dwilson, UGrid, resid,EvalImNormSmall);
|
||||||
// KrySchur(src[0], maxIter, Nm, Nk, Nstop);
|
// KrySchur(src[0], maxIter, Nm, Nk, Nstop);
|
||||||
@@ -357,10 +345,8 @@ int main (int argc, char ** argv)
|
|||||||
Nblock=LanParams.Nblock;
|
Nblock=LanParams.Nblock;
|
||||||
bool if_verify=false;
|
bool if_verify=false;
|
||||||
if(LanParams.verify) if_verify=true;
|
if(LanParams.verify) if_verify=true;
|
||||||
// KrylovSchur KrySchur (Dwilson, UGrid, resid,EvalImNormSmall);
|
// BlockKrylovSchur KrySchur (Dwilson, UGrid, resid,EvalImNormSmall);
|
||||||
// KrySchur(src, maxIter, Nm, Nk, Nstop,true,if_verify);
|
HarmonicBlockKrylovSchur KrySchur (Dwilson, UGrid, resid,shift,EvalNormSmall);
|
||||||
BlockKrylovSchur KrySchur (Dwilson, UGrid, resid,EvalImNormSmall);
|
|
||||||
// HarmonicBlockKrylovSchur KrySchur (Dwilson, UGrid, resid,shift,EvalImNormSmall);
|
|
||||||
KrySchur(src, maxIter, Nm, Nk, Nstop,Nblock,true,if_verify);
|
KrySchur(src, maxIter, Nm, Nk, Nstop,Nblock,true,if_verify);
|
||||||
std::cout << GridLogMessage << "BlockKrylovSchur evec.size= " << KrySchur.evecs.size()<< std::endl;
|
std::cout << GridLogMessage << "BlockKrylovSchur evec.size= " << KrySchur.evecs.size()<< std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -61,11 +61,11 @@ int main(int argc, char** argv)
|
|||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// Parameters (kept small so output is readable)
|
// Parameters (kept small so output is readable)
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
const int Nblock = 2;
|
const int Nblock = 4;
|
||||||
const int Nm = 12; // total vectors (= 6 blocks * Nblock=2)
|
const int Nm = 20; // total vectors (= 5 blocks * Nblock=4)
|
||||||
const int Nk = 6; // total kept (= 3 blocks * Nblock=2)
|
const int Nk = 8; // total kept (= 2 blocks * Nblock=4)
|
||||||
const int Nstop = 2;
|
const int Nstop = 4;
|
||||||
const int maxIter = 4;
|
const int maxIter = 8;
|
||||||
const RealD tol = 1e-6;
|
const RealD tol = 1e-6;
|
||||||
|
|
||||||
// Two identical starting blocks
|
// Two identical starting blocks
|
||||||
@@ -73,7 +73,7 @@ int main(int argc, char** argv)
|
|||||||
std::vector<Field> v0b(Nblock, Field(grid));
|
std::vector<Field> v0b(Nblock, Field(grid));
|
||||||
for (int t = 0; t < Nblock; t++) {
|
for (int t = 0; t < Nblock; t++) {
|
||||||
random(RNG, v0[t]);
|
random(RNG, v0[t]);
|
||||||
v0b[t] = v0[t];
|
v0b[t] = v0[t]; // identical start for fair comparison
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
@@ -87,7 +87,7 @@ int main(int argc, char** argv)
|
|||||||
std::cout << GridLogMessage
|
std::cout << GridLogMessage
|
||||||
<< "========================================\n" << std::endl;
|
<< "========================================\n" << std::endl;
|
||||||
|
|
||||||
BlockKrylovSchur<Field> bks(op, grid, tol, EvalReSmall);
|
BlockKrylovSchur<Field> bks(op, grid, tol, EvalImNormSmall);
|
||||||
bks(v0, maxIter, Nm, Nk, Nstop, Nblock,
|
bks(v0, maxIter, Nm, Nk, Nstop, Nblock,
|
||||||
/*doubleOrthog=*/true, /*doVerify=*/true);
|
/*doubleOrthog=*/true, /*doVerify=*/true);
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ int main(int argc, char** argv)
|
|||||||
std::cout << GridLogMessage
|
std::cout << GridLogMessage
|
||||||
<< "========================================\n" << std::endl;
|
<< "========================================\n" << std::endl;
|
||||||
|
|
||||||
HarmonicBlockKrylovSchur<Field> hbks(op, grid, tol, 0.0, EvalNormSmall);
|
HarmonicBlockKrylovSchur<Field> hbks(op, grid, tol, 0.0, EvalImNormSmall);
|
||||||
hbks(v0b, maxIter, Nm, Nk, Nstop, Nblock,
|
hbks(v0b, maxIter, Nm, Nk, Nstop, Nblock,
|
||||||
/*doubleOrthog=*/true, /*doVerify=*/true);
|
/*doubleOrthog=*/true, /*doVerify=*/true);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user