Sorting eval/evec according to RitzFilter

This commit is contained in:
Chulwoo Jung
2026-04-23 16:28:48 -04:00
parent f14be5e331
commit 7752e7ead1
5 changed files with 62 additions and 25 deletions
+18 -2
View File
@@ -30,6 +30,7 @@ See the full license in the file "LICENSE" in the top level distribution directo
#define GRID_BLOCKED_KRYLOV_SCHUR_H
#include <iomanip>
#include <numeric>
NAMESPACE_BEGIN(Grid);
@@ -697,8 +698,22 @@ private:
{
Eigen::ComplexEigenSolver<CMat> es;
es.compute(Hk);
evals = es.eigenvalues();
littleEvecs = es.eigenvectors();
// Sort to match schurReorder ordering.
int n = es.eigenvalues().size();
ComplexComparator cComp(ritzFilter);
std::vector<int> idx(n);
std::iota(idx.begin(), idx.end(), 0);
std::sort(idx.begin(), idx.end(), [&](int a, int b){
return cComp(toStdCmplx(es.eigenvalues()(a)), toStdCmplx(es.eigenvalues()(b)));
});
evals.resize(n);
littleEvecs.resize(n, n);
for (int k = 0; k < n; k++) {
evals(k) = es.eigenvalues()(idx[k]);
littleEvecs.col(k) = es.eigenvectors().col(idx[k]);
}
evecs.clear();
for (int k = 0; k < Nkeep; k++) {
@@ -735,6 +750,7 @@ private:
std::cout << GridLogMessage << "BlockKrylovSchur: Ritz estimate[" << k
<< "] = " << res << " eval = " << evals[k] << std::endl;
if (res < rtol) Nconv++;
else break;
}
return Nconv;
}
@@ -30,6 +30,7 @@ See the full license in the file "LICENSE" in the top level distribution directo
#define GRID_HARMONIC_BLOCKED_KRYLOV_SCHUR_H
#include <iomanip>
#include <numeric>
NAMESPACE_BEGIN(Grid);
@@ -574,8 +575,22 @@ private:
{
Eigen::ComplexEigenSolver<CMat> es;
es.compute(Hk);
evals = es.eigenvalues();
littleEvecs = es.eigenvectors();
// Sort to match schurReorder ordering.
int n = es.eigenvalues().size();
ComplexComparator cComp(ritzFilter);
std::vector<int> idx(n);
std::iota(idx.begin(), idx.end(), 0);
std::sort(idx.begin(), idx.end(), [&](int a, int b){
return cComp(toStdCmplx(es.eigenvalues()(a)), toStdCmplx(es.eigenvalues()(b)));
});
evals.resize(n);
littleEvecs.resize(n, n);
for (int k = 0; k < n; k++) {
evals(k) = es.eigenvalues()(idx[k]);
littleEvecs.col(k) = es.eigenvectors().col(idx[k]);
}
evecs.clear();
for (int k = 0; k < Nkeep; k++) {
@@ -612,6 +627,7 @@ private:
<< "HarmonicBlockKrylovSchur: Ritz estimate[" << k
<< "] = " << res << " eval = " << evals[k] << std::endl;
if (res < rtol) Nconv++;
else break;
}
return Nconv;
}
+20 -19
View File
@@ -105,8 +105,8 @@ struct ComplexComparator
bool operator()(std::complex<double> z1, std::complex<double> z2) {
RealD tmp1=std::abs(std::imag(z1));
RealD tmp2=std::abs(std::imag(z2));
if ( std::abs(std::real(z1)) >4.) tmp1 += 100.;
if ( std::abs(std::real(z2)) >4.) tmp2 += 100.;
if ( std::abs(std::real(z1)) >2.) tmp1 += 100.;
if ( std::abs(std::real(z2)) >2.) tmp2 += 100.;
switch (RF) {
case EvalNormSmall:
return std::abs(z1) < std::abs(z2);
@@ -738,35 +738,36 @@ if (!shift){
{
std::cout << GridLogMessage << "Computing eigenvalues." << std::endl;
// evals = S.diagonal();
int n = evals.size(); // should be regular Nm
evecs.clear();
// evecs.assign(n, Field(Grid));
// TODO: is there a faster way to get the eigenvectors of a triangular matrix?
// Rayleigh.triangularView<Eigen::Upper> tri;
Eigen::ComplexEigenSolver<Eigen::MatrixXcd> es;
// es.compute(Rayleigh);
es.compute(S);
evals = es.eigenvalues();
littleEvecs = es.eigenvectors();
// std::cout << GridLogDebug << "Little evecs: " << littleEvecs << std::endl;
// std::cout << "Rayleigh diag: " << S.diagonal() << std::endl;
// std::cout << "Rayleigh evals: " << evals << std::endl;
// Sort eigenvalues/evecs to match the schurReorder ordering.
int n = es.eigenvalues().size();
ComplexComparator cComp(ritzFilter);
std::vector<int> idx(n);
std::iota(idx.begin(), idx.end(), 0);
std::sort(idx.begin(), idx.end(), [&](int a, int b){
return cComp(toStdCmplx(es.eigenvalues()(a)), toStdCmplx(es.eigenvalues()(b)));
});
evals.resize(n);
littleEvecs.resize(n, n);
for (int k = 0; k < n; k++) {
evals(k) = es.eigenvalues()(idx[k]);
littleEvecs.col(k) = es.eigenvectors().col(idx[k]);
}
// Convert evecs to lattice fields
for (int k = 0; k < n; k++) {
Eigen::VectorXcd vec = littleEvecs.col(k);
Field tmp (basis[0].Grid());
tmp = Zero();
for (int j = 0; j < basis.size(); j++) {
for (int j = 0; j < (int)basis.size(); j++) {
tmp = tmp + vec[j] * basis[j];
}
evecs.push_back(tmp);
// evecs[k] = tmp;
}
}
@@ -831,12 +832,12 @@ if (!shift){
Eigen::VectorXcd evec_k = littleEvecs.col(k);
RealD ritzEstimate = std::abs(b.dot(evec_k)); // b^\dagger s
ritzEstimates.push_back(ritzEstimate);
// ritzEstimates[k] = ritzEstimate;
std::cout << GridLogMessage << "Ritz estimate for evec " << k << " = " << ritzEstimate << std::endl;
if (ritzEstimate < rtol) {
Nconv++;
} else {
break;
}
}
// Check that Ritz estimate is explicitly || D (Uy) - lambda (Uy) ||
// checkRitzEstimate();
+4 -2
View File
@@ -338,6 +338,7 @@ int main (int argc, char ** argv)
#if 0
KrylovSchur KrySchur (Dwilson, UGrid, resid,EvalImNormSmall);
// KrySchur(src[0], maxIter, Nm, Nk, Nstop);
KrySchur.doEvalCheck=true;
KrySchur(src[0], maxIter, Nm, Nk, Nstop,&shift);
std::cout << GridLogMessage << "KrylovSchur evec.size= " << KrySchur.evecs.size()<< std::endl;
#else
@@ -345,8 +346,9 @@ int main (int argc, char ** argv)
Nblock=LanParams.Nblock;
bool if_verify=false;
if(LanParams.verify) if_verify=true;
// BlockKrylovSchur KrySchur (Dwilson, UGrid, resid,EvalImNormSmall);
HarmonicBlockKrylovSchur KrySchur (Dwilson, UGrid, resid,shift,EvalNormSmall);
BlockKrylovSchur KrySchur (Dwilson, UGrid, resid,EvalImNormSmall);
// HarmonicBlockKrylovSchur KrySchur (Dwilson, UGrid, resid,shift,EvalNormSmall);
KrySchur.doEvalCheck=true;
KrySchur(src, maxIter, Nm, Nk, Nstop,Nblock,true,if_verify);
std::cout << GridLogMessage << "BlockKrylovSchur evec.size= " << KrySchur.evecs.size()<< std::endl;
#endif
+2
View File
@@ -10,8 +10,10 @@
<Np>100</Np>
<ReadEvec>0</ReadEvec>
<maxIter>1000</maxIter>
<reorthog>1</reorthog>
<Nblock>4</Nblock>
<verify>0</verify>
<shift>1.5</shift>
<resid>1e-10</resid>
<ChebyLow>1</ChebyLow>
<ChebyHigh>100</ChebyHigh>