00001
00002
00003
00004
00005
00006
00007 #include "chromabase.h"
00008
00009 #include <sstream>
00010
00011 #include "meas/eig/eig_spec.h"
00012 #include "meas/eig/ritz.h"
00013 #include "meas/eig/sn_jacob.h"
00014
00015 namespace Chroma {
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 void EigSpecRitzCG(const LinearOperator<LatticeFermion>& M,
00043 multi1d<Real>& lambda_H,
00044 multi1d<LatticeFermion>& psi,
00045 int n_eig,
00046 int n_renorm,
00047 int n_min,
00048 int MaxCG,
00049 const Real& Rsd_r,
00050
00051 const Real& Rsd_a,
00052 const Real& zero_cutoff,
00053
00054 const bool ProjApsiP,
00055
00056 int& n_cg_tot,
00057 XMLWriter& xml_out
00058 )
00059 {
00060 START_CODE();
00061
00062 const Subset& sub = M.subset();
00063
00064 push(xml_out, "EigSpecRitzCG");
00065
00066
00067 n_cg_tot = 0;
00068 int n_count = 0;
00069 int n_max = MaxCG+1;
00070
00071 int n, i;
00072 Real final_grad;
00073
00074 multi1d<Real> resid_rel(n_eig);
00075 for(n = 1, i = 0; n <= n_eig; n++, i++) {
00076
00077
00078 lambda_H[i] = Real(1);
00079
00080
00081 Ritz(M, lambda_H[i], psi, n, Rsd_r, Rsd_a, zero_cutoff, n_renorm, n_min,
00082 n_max, MaxCG, ProjApsiP, n_count, final_grad, false, Real(1),
00083 Real(1));
00084
00085
00086 n_cg_tot += n_count;
00087
00088
00089 ostringstream s;
00090 s << "eval" << n;
00091 push(xml_out, s.str());
00092 write(xml_out, "n_count", n_count);
00093 pop(xml_out);
00094
00095 if( toBool( fabs(lambda_H[i]) < zero_cutoff ) )
00096 {
00097 QDPIO::cout << "Evalue["<< n << "] = " << lambda_H[i] << " is considered zero" << endl;
00098 }
00099 else
00100 {
00101 LatticeFermion D_e;
00102 LatticeFermion lambda_e;
00103 M(D_e, psi[i], PLUS);
00104 lambda_e[sub] = lambda_H[i]*psi[i];
00105 D_e[sub] -= lambda_e;
00106 Double r_norm = sqrt(norm2(D_e,sub));
00107 resid_rel[i] = Real(r_norm)/lambda_H[i];
00108 QDPIO::cout << "Evalue["<<n<<"]: eigen_norm = " << r_norm << " resid_rel = " << resid_rel[i] << endl << endl;
00109 }
00110 }
00111
00112
00113 push(xml_out, "eValues");
00114 write(xml_out, "lambda", lambda_H);
00115 pop(xml_out);
00116 write(xml_out, "n_cg_tot", n_cg_tot);
00117
00118 pop(xml_out);
00119
00120
00121 END_CODE();
00122 }
00123
00124
00125 void EigSpecRitzKS(const LinearOperator<LatticeFermion>& M,
00126 multi1d<Real>& lambda_H,
00127 multi1d<LatticeFermion>& psi,
00128 int n_eig,
00129 int n_dummy,
00130
00131 int n_renorm,
00132 int n_min,
00133 int n_max,
00134 int n_max_KS,
00135 const Real& gamma_factor,
00136
00137 int MaxCG,
00138 const Real& Rsd_r,
00139
00140 const Real& Rsd_a,
00141 const Real& zero_cutoff,
00142
00143 const bool ProjApsiP,
00144
00145 int& n_cg_tot,
00146 int& n_KS,
00147 int& n_jacob_tot,
00148 XMLWriter& xml_out
00149 )
00150 {
00151 START_CODE();
00152
00153 const Subset& s = M.subset();
00154
00155
00156
00157 if( lambda_H.size() < (n_eig+n_dummy) ) {
00158 QDP_error_exit("lambda_H is too small to hold n_eig + n_dummy values\n");
00159 }
00160
00161
00162 if( psi.size() < (n_eig + n_dummy) ) {
00163 QDP_error_exit("psi is too small to hold n_eig + n_dummy values\n");
00164 }
00165
00166 if( n_eig <=0 ) {
00167 QDP_error_exit("n_eig must be > 0. it is %d\n", n_eig);
00168 }
00169
00170
00171 if( n_eig ==1 ) {
00172
00173
00174 EigSpecRitzCG(M, lambda_H, psi, n_eig, n_renorm, n_min, MaxCG, Rsd_r,
00175 Rsd_a, zero_cutoff, ProjApsiP, n_cg_tot, xml_out);
00176 return;
00177 }
00178
00179
00180
00181 int n_working_eig = n_eig+n_dummy;
00182 multi1d<Real> lambda_intern(n_working_eig);
00183 multi1d<Real> lambda_previous(n_working_eig);
00184 multi1d<Real> delta_cycle(n_working_eig);
00185 int i;
00186 for(i = 0; i < n_working_eig; i++) {
00187 lambda_intern[i] = lambda_H[i];
00188 lambda_previous[i] = Real(1);
00189 delta_cycle[i] = Real(1);
00190 }
00191
00192
00193 multi1d<Complex> off_diag((n_working_eig)*(n_working_eig-1)/2);
00194
00195
00196 multi1d<Real> final_grad(n_working_eig);
00197
00198 int n_count = 0;
00199 n_cg_tot = 0;
00200 n_KS = 0;
00201 n_jacob_tot = 0;
00202
00203 int ev, j, ij;
00204 int n_jacob;
00205
00206 push(xml_out, "EigSpecRitzKS");
00207
00208 bool convP = false;
00209
00210 for( int KS_iter = 0; KS_iter < n_max_KS; KS_iter++) {
00211 n_KS++;
00212
00213 push(xml_out, "KS_iter");
00214
00215
00216
00217
00218 for(ev = 1, i=0; ev <= n_working_eig; ev++, i++) {
00219
00220
00221 Ritz(M, lambda_intern[i], psi, ev, Rsd_r, Rsd_a, zero_cutoff, n_renorm,
00222 n_min, n_max, MaxCG, ProjApsiP, n_count, final_grad[i], true,
00223 Real(1), gamma_factor);
00224
00225
00226 n_cg_tot += n_count;
00227 push(xml_out, "ev");
00228 write(xml_out, "n_count", n_count);
00229 write(xml_out, "final_grad", final_grad[i]);
00230 pop(xml_out);
00231
00232 }
00233
00234
00235
00236
00237
00238
00239
00240 LatticeFermion tmp;
00241 for(i=0, ij=0; i < n_working_eig; i++) {
00242 M(tmp, psi[i], PLUS);
00243 for(j=0; j < i; j++) {
00244 off_diag[ij] = innerProduct(psi[j], tmp);
00245 ij++;
00246 }
00247 }
00248
00249
00250
00251
00252
00253
00254 n_jacob = SN_Jacob(psi, n_working_eig, lambda_intern, off_diag, Rsd_a, 50, s);
00255 n_jacob_tot += n_jacob;
00256
00257 write(xml_out, "n_jacob", n_jacob);
00258
00259
00260
00261
00262
00263
00264 bool convP = true;
00265 for(i=0; i < n_eig; i++) {
00266 bool zeroReachedP = toBool( fabs(lambda_intern[i]) < zero_cutoff );
00267
00268
00269
00270
00271
00272
00273 convP &= ( toBool( final_grad[i] < Rsd_a )
00274 || toBool( final_grad[i] < Rsd_r*fabs(lambda_intern[i]) )
00275 || zeroReachedP );
00276 }
00277
00278 pop(xml_out);
00279
00280
00281 if( convP ) {
00282
00283
00284
00285 for(i=0, ij=0; i < n_eig; i++) {
00286 M(tmp, psi[i], PLUS);
00287 for(j=0; j < i; j++) {
00288 off_diag[ij] = innerProduct(psi[j], tmp);
00289 ij++;
00290 }
00291 }
00292
00293
00294 n_jacob = SN_Jacob(psi, n_eig, lambda_intern, off_diag, Rsd_a, 50, s);
00295 write(xml_out, "final_n_jacob", n_jacob);
00296 write(xml_out, "n_cg_tot", n_cg_tot);
00297 write(xml_out, "n_KS", n_KS);
00298
00299
00300
00301 for(i=0; i < n_eig; i++) {
00302 lambda_H[i] = lambda_intern[i];
00303 }
00304
00305 write(xml_out, "lambda_H", lambda_H);
00306 pop(xml_out);
00307 END_CODE();
00308 return;
00309 }
00310
00311 }
00312
00313 write(xml_out, "n_cg_tot", n_cg_tot);
00314 write(xml_out, "n_KS", n_KS);
00315 pop(xml_out);
00316
00317
00318 QDP_error_exit("n_max_KS reached with no convergence");
00319 END_CODE();
00320 }
00321
00322
00323 void fixMMev2Mev(const LinearOperator<LatticeFermion>& M,
00324 multi1d<Real>& lambda,
00325
00326 multi1d<LatticeFermion>& ev_psi,
00327 const int n_eig,
00328 const Real& Rsd_r,
00329 const Real& Rsd_a,
00330 const Real& zero_cutoff,
00331 multi1d<bool>& valid_eig,
00332 int& n_valid,
00333 int& n_jacob
00334 )
00335 {
00336 START_CODE();
00337
00338 const Subset& s = M.subset();
00339
00340
00341 if( n_eig > lambda.size() ) {
00342 QDP_error_exit("n_eig greater than size of lambda array\n");
00343 }
00344
00345 if( lambda.size() != ev_psi.size() ) {
00346 QDP_error_exit("lambda and ev_psi arrays must have same size\n");
00347 }
00348
00349
00350 valid_eig.resize(n_eig);
00351
00352
00353 LatticeFermion tmp;
00354 Double lambda_H_sq;
00355 Double delta_lambda;
00356 bool zeroMatchedP;
00357 bool convP;
00358
00359
00360 if( n_eig == 1 ) {
00361 M(tmp, ev_psi[0], PLUS);
00362 Double lambda_fix_single = innerProductReal(ev_psi[0], tmp);
00363
00364
00365
00366
00367 lambda_H_sq = lambda_fix_single*lambda_fix_single;
00368
00369
00370
00371
00372 if( toBool( lambda_H_sq < zero_cutoff ) ) {
00373
00374
00375
00376
00377
00378 if( toBool( lambda[0] < zero_cutoff ) ) {
00379 valid_eig[0] = true;
00380 n_valid = 1;
00381 }
00382 else {
00383
00384
00385 valid_eig[0] = false;
00386 n_valid = 1;
00387 }
00388 }
00389 else {
00390
00391 delta_lambda = fabs( lambda_H_sq - Double( lambda[0] ) );
00392
00393 convP = toBool( delta_lambda < Double(Rsd_a) )
00394 || toBool( delta_lambda < Double(Rsd_r)*fabs(Double(lambda[0])) );
00395
00396 if ( convP ) {
00397
00398 valid_eig[0] = true;
00399 n_valid = 1;
00400 } else {
00401
00402 valid_eig[0] = false;
00403 n_valid = 0;
00404 }
00405 }
00406
00407
00408
00409 lambda[0] = Real(lambda_fix_single);
00410 return;
00411 }
00412
00413
00414
00415
00416 multi1d<Complex> off_diag(n_eig*(n_eig-1)/2 );
00417 multi1d<Real> lambda_fix(n_eig);
00418 for(int i = 0; i < n_eig; i++) {
00419 valid_eig[i] = false;
00420 }
00421
00422 for(int i=0, ij=0; i < n_eig; i++) {
00423 M(tmp, ev_psi[i], PLUS);
00424 lambda_fix[i] = innerProductReal(ev_psi[i], tmp);
00425
00426 for(int j=0; j < i; j++) {
00427 off_diag[ij] = innerProduct(ev_psi[j], tmp);
00428 ij++;
00429 }
00430 }
00431
00432
00433 n_jacob = SN_Jacob(ev_psi, n_eig, lambda_fix, off_diag, Rsd_a, 50, s);
00434
00435
00436 n_valid = 0;
00437
00438 for(int i=0; i < n_eig; i++) {
00439
00440 lambda_H_sq = Double(lambda_fix[i])*Double(lambda_fix[i]);
00441
00442
00443 if( toBool(lambda_H_sq < zero_cutoff ) ) {
00444
00445
00446 for(int j = n_valid; ( j < n_eig ) && ( valid_eig[i] == false ); j++ ) {
00447
00448
00449
00450 if( toBool( lambda[j] < zero_cutoff ) ) {
00451
00452
00453 valid_eig[i] = true;
00454
00455
00456
00457 Real tmp = lambda[j];
00458 lambda[j] = lambda[n_valid];
00459 lambda[n_valid] = tmp;
00460
00461
00462 n_valid++;
00463 }
00464
00465
00466 }
00467
00468
00469
00470
00471 }
00472 else {
00473
00474 for(int j = n_valid; ( j < n_eig ) && ( valid_eig[i] == false ); j++ ) {
00475 delta_lambda = fabs( lambda_H_sq - Double(lambda[j]) );
00476
00477 convP = toBool( delta_lambda < Double(Rsd_a) )
00478 || toBool( delta_lambda < Double(Rsd_r) * fabs( Double(lambda[j]) ) );
00479 if( convP ) {
00480
00481
00482 valid_eig[i] = true;
00483
00484
00485
00486 Real tmp = lambda[j];
00487 lambda[j] = lambda[n_valid];
00488 lambda[n_valid] = tmp;
00489
00490
00491 n_valid++;
00492 }
00493
00494
00495 }
00496
00497
00498
00499 }
00500 }
00501
00502
00503
00504
00505 for(int i = 0; i < n_eig; i++ ) {
00506 lambda[i] = lambda_fix[i];
00507 }
00508
00509 END_CODE();
00510
00511
00512 return;
00513 }
00514
00515 }