00001 #include "chromabase.h"
00002
00003 #include "actions/ferm/qprop/asqtad_cps_wrapper_qprop.h"
00004 #include "actions/ferm/invert/syssolver_cg_params.h"
00005 #include "util/gauge/stag_phases_s.h"
00006
00007
00008 extern "C" {
00009
00010
00011 #define LEVEL3_PREC 2
00012
00013 #if LEVEL3_PREC == 2
00014
00015 #define QLA_Precision 'D'
00016 #define QOP_Precision 2
00017 #else
00018
00019 #define QLA_Precision 'F'
00020 #define QOP_Precision 1
00021 #endif
00022
00023
00024 #define QLA_Colors 3
00025
00026 #include <qdp.h>
00027 #include <qdp_types.h>
00028 #include <qdp_common.h>
00029
00030 #if LEVEL3_PREC == 2
00031 #include <qdp_d3_generic.h>
00032 #include <qdp_d3.h>
00033 #else
00034 #include <qdp_f3_generic.h>
00035 #include <qdp_f3.h>
00036 #endif
00037
00038 #include <qop_qdp.h>
00039 #include <qmp.h>
00040
00041 #include <qla.h>
00042 #include <qla_complex.h>
00043
00044
00045 }
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 QLA_Real
00063 get_plaq(QDP_ColorMatrix *link[])
00064 {
00065 int mu, nu;
00066 QLA_Real plaq;
00067 QDP_ColorMatrix *temp1, *temp2, *temp3, *temp4;
00068
00069 #ifdef LOCAL_SUM
00070 QDP_Real *treal1, *treal2;
00071 treal1 = QDP_create_R();
00072 treal2 = QDP_create_R();
00073 QDP_R_eq_zero(treal2, QDP_all);
00074 #else
00075 QLA_Real tplaq;
00076 plaq = 0;
00077 #endif
00078
00079 temp1 = QDP_create_M();
00080 temp2 = QDP_create_M();
00081 temp3 = QDP_create_M();
00082 temp4 = QDP_create_M();
00083
00084
00085
00086 for(mu=0; mu<QDP_ndim()-1; ++mu) {
00087 for(nu=mu+1; nu<QDP_ndim(); ++nu) {
00088
00089 QDP_M_eq_sM(temp1, link[nu], QDP_neighbor[mu], QDP_forward, QDP_all);
00090 QDP_M_eq_sM(temp2, link[mu], QDP_neighbor[nu], QDP_forward, QDP_all);
00091
00092 QDP_M_eq_Ma_times_M(temp3, link[nu], link[mu], QDP_all);
00093
00094 QDP_M_eq_M_times_M(temp4, temp3, temp1, QDP_all);
00095 QDP_discard_M(temp1);
00096
00097 #ifdef LOCAL_SUM
00098 QDP_R_eq_re_M_dot_M(treal1, temp2, temp4, QDP_all);
00099 QDP_discard_M(temp2);
00100 QDP_R_peq_R(treal2, treal1, QDP_all);
00101 #else
00102 QDP_r_eq_re_M_dot_M(&tplaq, temp2, temp4, QDP_all);
00103 QDP_discard_M(temp2);
00104 plaq += tplaq;
00105 #endif
00106
00107 }
00108 }
00109
00110 #ifdef LOCAL_SUM
00111 QDP_r_eq_sum_R(&plaq, treal2, QDP_all);
00112 QDP_destroy_R(treal1);
00113 QDP_destroy_R(treal2);
00114 #endif
00115
00116 QDP_destroy_M(temp1);
00117 QDP_destroy_M(temp2);
00118 QDP_destroy_M(temp3);
00119 QDP_destroy_M(temp4);
00120
00121
00122 return plaq/(3.0*0.5*QDP_ndim()*(QDP_ndim()-1)*QDP_volume());
00123 }
00124
00125
00126
00127
00128
00129
00130
00131 QDP_ColorMatrix ** QDP_create_gauge_from_chroma (
00132 multi1d<LatticeColorMatrix> & u_chroma)
00133 {
00134 QDP_ColorMatrix **u;
00135
00136 const int ndim = 4 ;
00137 u = (QDP_ColorMatrix **) malloc(ndim*sizeof(QDP_ColorMatrix *));
00138 for(int i=0; i<ndim; i++) u[i] = QDP_create_M();
00139
00140
00141 QLA_ColorMatrix *tmp;
00142 tmp =
00143 (QLA_ColorMatrix *) malloc(QDP_sites_on_node*sizeof(QLA_ColorMatrix));
00144
00145 for(int i=0; i<ndim; i++)
00146 {
00147 for(int site=0 ; site < QDP_sites_on_node ; ++site)
00148 {
00149 for(int ic = 0 ; ic < 3 ; ++ic)
00150 for(int jc = 0 ; jc < 3 ; ++jc)
00151 {
00152
00153 Real rrr = u_chroma[i].elem(site).elem().elem(ic,jc).real() ;
00154 Real iii = u_chroma[i].elem(site).elem().elem(ic,jc).imag() ;
00155
00156 QLA_Real zre = toFloat(rrr) ;
00157 QLA_Real zim = toFloat(iii) ;
00158 QLA_Complex z ;
00159 QLA_C_eq_R_plus_i_R(&z,&zre,&zim) ;
00160
00161
00162 QLA_M_eq_elem_C(&tmp[site],&z,ic,jc) ;
00163 }
00164
00165
00166 }
00167
00168 QDP_insert_M(u[i], tmp,QDP_all) ;
00169 }
00170
00171 free(tmp) ;
00172
00173
00174
00175 QLA_Real plaq;
00176 plaq = get_plaq(u);
00177 QDPIO::cout << "QDP_create_gauge_from_chroma:: plaquette = " << plaq << "\n";
00178
00179 return u ;
00180 }
00181
00182
00183
00184
00185
00186 void convert_chroma_to_qdp(QDP_ColorVector *out,
00187 const LatticeStaggeredFermion & in )
00188 {
00189 QLA_ColorVector *tmp;
00190 tmp =
00191 (QLA_ColorVector *) malloc(QDP_sites_on_node*sizeof(QLA_ColorVector));
00192
00193 for(int site=0 ; site < QDP_sites_on_node ; ++site)
00194 {
00195
00196 for(int ic = 0 ; ic < 3 ; ++ic)
00197 {
00198 QLA_Real zre ;
00199
00200 Real rrr = in.elem(site).elem(0).elem(ic).real() ;
00201 Real iii = in.elem(site).elem(0).elem(ic).imag() ;
00202
00203 zre = toFloat(rrr) ;
00204 QLA_Real zim = toFloat(iii) ;
00205 QLA_Complex z ;
00206 QLA_C_eq_R_plus_i_R(&z,&zre,&zim) ;
00207
00208 QLA_V_eq_elem_C(&tmp[site],&z,ic) ;
00209
00210
00211 }
00212
00213 }
00214
00215
00216 QDP_insert_V(out, tmp,QDP_all) ;
00217
00218
00219 free(tmp) ;
00220
00221 }
00222
00223
00224
00225
00226
00227
00228
00229 void convert_qdp_to_chroma(LatticeStaggeredFermion & out,
00230 QDP_ColorVector *in)
00231 {
00232 Complex zz ;
00233 QLA_Complex z ;
00234
00235 QLA_ColorVector *tmp;
00236 tmp = QDP_expose_V(in) ;
00237
00238
00239 for(int site=0 ; site < QDP_sites_on_node ; ++site)
00240 {
00241 for(int ic = 0 ; ic < 3 ; ++ic)
00242 {
00243 QLA_C_eq_elem_V(&z,&tmp[site],ic) ;
00244
00245 QLA_Real zre ;
00246 zre = QLA_real(z) ;
00247
00248 QLA_Real zim ;
00249 zim = QLA_imag(z) ;
00250
00251 Real zre_chroma , zim_chroma ;
00252 zre_chroma = (Real) zre ;
00253 zim_chroma = (Real) zim ;
00254
00255
00256
00257
00258 zre_chroma /= 2.0 ;
00259 zim_chroma /= 2.0 ;
00260
00261 out.elem(site).elem(0).elem(ic).real() = toFloat(zre_chroma) ;
00262 out.elem(site).elem(0).elem(ic).imag() = toFloat(zim_chroma) ;
00263
00264
00265
00266
00267 }
00268
00269 }
00270
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 void load_qop_asqtad_coeffs(QOP_asqtad_coeffs_t *c, QLA_Real weight)
00282 {
00283 QLA_Real ferm_epsilon;
00284 #define MAX_BASIC_PATHS 6
00285 static QLA_Real act_path_coeff[MAX_BASIC_PATHS] = {
00286 ( 1.0/8.0)+(6.0/16.0)+(1.0/8.0),
00287
00288 (-1.0/24.0),
00289 (-1.0/8.0)*0.5,
00290 ( 1.0/8.0)*0.25*0.5,
00291 (-1.0/8.0)*0.125*(1.0/6.0),
00292 (-1.0/16 ),
00293 };
00294
00295
00296
00297
00298
00299 ferm_epsilon = weight;
00300
00301
00302
00303 c->one_link = act_path_coeff[0]*ferm_epsilon ;
00304 c->naik = act_path_coeff[1]*ferm_epsilon ;
00305 c->three_staple = act_path_coeff[2]*ferm_epsilon ;
00306 c->five_staple = act_path_coeff[3]*ferm_epsilon ;
00307 c->seven_staple = act_path_coeff[4]*ferm_epsilon ;
00308 c->lepage = act_path_coeff[5]*ferm_epsilon ;
00309 }
00310
00311
00312
00313
00314
00315
00316
00317 namespace Chroma
00318 {
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 static QDP_ColorVector *out ;
00332 static QDP_ColorVector *in ;
00333
00334
00335 static QOP_info_t info;
00336 static QOP_FermionLinksAsqtad *fla ;
00337
00338
00339
00340 AsqtadCPSWrapperQprop::AsqtadCPSWrapperQprop(
00341 const EvenOddStaggeredTypeFermAct<LatticeStaggeredFermion,
00342 multi1d<LatticeColorMatrix>,
00343 multi1d<LatticeColorMatrix> >& S_,
00344 Handle< FermState<LatticeStaggeredFermion,P,Q> > state_,
00345 const SysSolverCGParams& invParam_) :
00346
00347 invParam(invParam_),Mass(S_.getQuarkMass()),
00348 state(state_.cast<AsqtadConnectStateBase>()) , M(S_.linOp(state_))
00349 {
00350
00351
00352 const multi1d<LatticeColorMatrix>& u = state->getLinks();
00353
00354 const multi1d<LatticeColorMatrix>& u_fat = state->getFatLinks();
00355 const multi1d<LatticeColorMatrix>& u_triple = state->getTripleLinks();
00356
00357 multi1d<LatticeColorMatrix> u_chroma(Nd);
00358
00359 QDP_ColorMatrix **u_fat_qdp;
00360 u_chroma = u_fat ;
00361 u_fat_qdp = QDP_create_gauge_from_chroma(u_chroma) ;
00362
00363
00364 QDP_ColorMatrix **u_triple_qdp;
00365 u_chroma = u_triple ;
00366 u_triple_qdp = QDP_create_gauge_from_chroma(u_chroma) ;
00367
00368
00369 fla = QOP_asqtad_convert_L_from_qdp(u_fat_qdp,u_triple_qdp) ;
00370
00371 #if 0
00372 for(int i=0; i<Nd ; i++) QDP_destroy_M(u_fat_qdp[i]);
00373 free(u_fat_qdp) ;
00374
00375
00376 for(int i=0; i<Nd; i++) QDP_destroy_M(u_triple_qdp[i]);
00377 free(u_triple_qdp) ;
00378
00379 #endif
00380
00381
00382 #if 0
00383 multi1d<LatticeColorMatrix> u_with_phases(Nd);
00384 state.getFermBC().modify(u_with_phases);
00385 #endif
00386
00387 #if 0
00388
00389 multi1d<LatticeColorMatrix> u_chroma(Nd);
00390
00391 for(int i = 0; i < Nd; i++) {
00392 u_chroma[i] = u[i] ;
00393 u_chroma[i] *= StagPhases::alpha(i);
00394 }
00395
00396
00397
00398 QOP_asqtad_coeffs_t coeffs;
00399 load_qop_asqtad_coeffs(&coeffs, 1.0) ;
00400 Real u0 = 1.0 ;
00401
00402
00403 QDP_ColorMatrix **uqdp ;
00404 uqdp = QDP_create_gauge_from_chroma (u_chroma) ;
00405
00406 QOP_GaugeField *gf;
00407 gf = QOP_convert_G_from_qdp(uqdp);
00408
00409
00410 fla = QOP_asqtad_create_L_from_G(&info, &coeffs, gf);
00411
00412
00413
00414
00415 QOP_destroy_G(gf) ;
00416 free(uqdp) ;
00417
00418 #endif
00419
00420 }
00421
00422
00423
00424 AsqtadCPSWrapperQprop::~AsqtadCPSWrapperQprop()
00425 {
00426 QOP_asqtad_destroy_L(fla) ;
00427
00428 }
00429
00430 SystemSolverResults_t
00431 AsqtadCPSWrapperQprop::operator() (LatticeStaggeredFermion& psi,
00432 const LatticeStaggeredFermion& q_source) const
00433 {
00434 SystemSolverResults_t res;
00435
00436
00437 out = QDP_create_V();
00438 in = QDP_create_V();
00439
00440
00441
00442 convert_chroma_to_qdp(in,q_source) ;
00443 convert_chroma_to_qdp(out,psi) ;
00444
00445 QOP_ColorVector *qopout, *qopin;
00446 qopout = QOP_create_V_from_qdp(out);
00447 qopin = QOP_create_V_from_qdp(in);
00448
00449 QOP_invert_arg_t inv_arg;
00450 QOP_resid_arg_t res_arg;
00451
00452 res_arg.rsqmin = toFloat(invParam.RsdCG)*
00453 toFloat(invParam.RsdCG);
00454
00455
00456 if( invParam.MaxCGRestart > 0 )
00457 inv_arg.max_restarts = invParam.MaxCGRestart ;
00458 else
00459 inv_arg.max_restarts = 1;
00460
00461 inv_arg.restart = invParam.MaxCG ;
00462 inv_arg.max_iter = inv_arg.max_restarts * invParam.MaxCG;
00463 inv_arg.evenodd = QOP_EVENODD ;
00464
00465 QLA_Real mass = toFloat(Mass) ;
00466
00467 QDPIO::cout << "level3 asqtad inverter mass = " << Mass ;
00468 QDPIO::cout << " iters = " << invParam.MaxCG << " restarts= " ;
00469 QDPIO::cout << inv_arg.max_restarts << "\n" ;
00470
00471
00472 QOP_verbose(QOP_VERB_HI);
00473 QOP_asqtad_invert(&info, fla, &inv_arg, &res_arg, mass, qopout, qopin);
00474
00475 QDPIO::cout << "QOP Inversion results\n" ;
00476 QDPIO::cout << "QOP iters = " << res_arg.final_iter << "\n" ;
00477 QDPIO::cout << "QOP final restart = " << res_arg.final_restart << "\n" ;
00478 QDPIO::cout << "QOP ||r||^2 = " << res_arg.final_rsq << "\n" ;
00479 QDPIO::cout << "QOP ||r|| = " << sqrt(res_arg.final_rsq) << "\n" ;
00480 res.n_count = res_arg.final_iter ;
00481 res.resid = res_arg.final_rsq;
00482
00483
00484 QOP_extract_V_to_qdp(out,qopout) ;
00485 convert_qdp_to_chroma(psi,out) ;
00486
00487
00488
00489 #if 0
00490 exit(0) ;
00491 Real mass_scale = 4.0 * Mass ;
00492
00493 T tt;
00494 tt = psi ;
00495 psi = tt / mass_scale ;
00496 #endif
00497
00498
00499 {
00500 T r;
00501 (*M)(r, psi, PLUS);
00502 r -= q_source ;
00503 res.resid = sqrt(norm2(r));
00504 QDPIO::cout << "AsqtadCPSWrapperQprop: true residual: " << res.resid << endl;
00505 QDPIO::cout << "AsqtadCPSWrapperQprop: || q_source ||: " << sqrt(norm2(q_source)) << endl;
00506
00507 QDPIO::cout << "AsqtadCPSWrapperQprop: true residual/source: " << res.resid/ sqrt(norm2(q_source)) << endl;
00508
00509 }
00510
00511 QOP_destroy_V(qopout);
00512 QOP_destroy_V(qopin);
00513
00514 QDP_destroy_V(out);
00515 QDP_destroy_V(in);
00516
00517 return res;
00518 }
00519
00520 }
00521
00522
00523 void setup_levelthree(multi1d<int> nrow, int *argc, char ***argv )
00524 {
00525
00526 int tmp = ::QDP_initialize(argc,argv ) ;
00527
00528 QDPIO::cout << "Setting up the level 3 code\n" ;
00529 QDPIO::cout << "----------------------------\n";
00530
00531 int ndim = 4;
00532 int *lattice_size;
00533 lattice_size = (int *) malloc(ndim*sizeof(int));
00534 for(int i=0 ; i < ndim ; ++i)
00535 lattice_size[i] = nrow[i] ;
00536
00537 QDPIO::cout << "QDP/QOP lattice volume = " ;
00538 QDPIO::cout << lattice_size[0] << " " << lattice_size[1] << " " ;
00539 QDPIO::cout << lattice_size[2] << " " << lattice_size[3] << "\n" ;
00540
00541 #if LEVEL3_PREC == 2
00542 QDPIO::cout << "DOUBLE PRECISION level3\n" ;
00543 #else
00544 QDPIO::cout << "SINGLE PRECISION level3\n" ;
00545 #endif
00546
00547
00548
00549 QDP_set_latsize(ndim, lattice_size);
00550 QDP_create_layout();
00551
00552
00553 QOP_layout_t qoplayout;
00554 qoplayout.latdim = ndim;
00555 qoplayout.latsize = (int *) malloc(ndim*sizeof(int));
00556 for(int i=0; i<ndim; i++) {
00557 qoplayout.latsize[i] = lattice_size[i];
00558 }
00559 qoplayout.machdim = -1;
00560 QOP_init(&qoplayout);
00561
00562
00563 free(lattice_size) ;
00564
00565 }
00566
00567