asqtad_cps_wrapper_qprop.cc

Go to the documentation of this file.
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 // double precision (recommended)
00011 #define LEVEL3_PREC 2
00012 
00013 #if LEVEL3_PREC == 2
00014 // double precision
00015 #define QLA_Precision 'D'
00016 #define QOP_Precision 2
00017 #else
00018 // single precision
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 /** level 3 interface code  **/
00052 
00053 
00054 //
00055 //  utility routines
00056 //
00057 
00058 //
00059 //  from test_common.c
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   // http://usqcd.jlab.org/usqcd-docs/qdp/qdpc.html/Functions-involving-shifts.html#Functions-involving-shifts
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   // normalisation of plaquette <p> = 1 for cold config.
00122   return plaq/(3.0*0.5*QDP_ndim()*(QDP_ndim()-1)*QDP_volume());
00123 }
00124 
00125 
00126 
00127 //
00128 // Convert the gaugefield from chroma/qdp++ format 
00129 // into qdp format.
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   // more work --- check error codes
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                 //              QDPIO::cout << "" << ic << " , " << jc << " = " << zre << " " << zim << endl ;
00162                 QLA_M_eq_elem_C(&tmp[site],&z,ic,jc) ; 
00163               }
00164 
00165           //      tmp[site]
00166         }
00167       // convert to qdp format
00168       QDP_insert_M(u[i], tmp,QDP_all) ; 
00169     }
00170 
00171   free(tmp) ; 
00172 
00173 
00174   // convert to QOP format.
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 // Convert the colorvector from chroma/qdp++ format 
00184 // into qdp format.
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           //      QDPIO::cout << "convert_chroma_to_qdp-DEBUG " << site << " " << ic << " " << zre << "  " <<  zim << "\n" ;
00211         }
00212 
00213     } // loop over sites
00214 
00215   // convert to qdp format
00216   QDP_insert_V(out, tmp,QDP_all) ; 
00217 
00218 
00219   free(tmp) ; 
00220 
00221 }
00222 
00223 
00224 
00225 //
00226 // Convert the colorvector in qdp into  chroma/qdp++ format 
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   // this is done at the pointer level
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           //      zre_chroma *= (4 * 0.03) ; 
00256           //    zim_chroma *= (4 * 0.03) ; 
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           //      QDPIO::cout << "convert_qdp_to_chroma-DEBUG " << site << " " << ic << " " << zre_chroma << " " << zim_chroma   << "\n" ;
00266 
00267         } // loop over color
00268 
00269     } // loop over sites
00270 
00271 }
00272 
00273 
00274 //
00275 // set the coefficients from the MILC code.
00276 // This routine came from 
00277 //           generic_ks/quark_stuff.c
00278 //           generic_ks/imp_actions/asqtad_action.h
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),        /* one link */
00287     /*One link is 1/8 as in fat7 +3/8 for Lepage + 1/8 for Naik */
00288     (-1.0/24.0),                 /* Naik */
00289     (-1.0/8.0)*0.5,              /* simple staple */
00290     ( 1.0/8.0)*0.25*0.5,         /* displace link in two directions */
00291     (-1.0/8.0)*0.125*(1.0/6.0),  /* displace link in three directions */
00292     (-1.0/16 ),                  /* Correct O(a^2) errors */
00293   };
00294 
00295 
00296   /* Load path coefficients from table */
00297   //  act_path_coeff = get_quark_path_coeff();
00298 
00299   ferm_epsilon = weight;
00300 
00301   /* Path coefficients times fermion epsilon */
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 /*** end of level 3 interface code ****/
00314 /**************************************/
00315 
00316 
00317 namespace Chroma 
00318 {
00319 
00320   //! Constructor
00321   /*!
00322   // Keeping the same interface as for the ordinary staggered 
00323   // qprop...
00324   //
00325   // But the M_ and A_ linop handles are no longer kept
00326   // (are ignored) -- is there a nice way around this ? 
00327   // Perhaps not
00328   */
00329 
00330     // internal variables to this file
00331 static  QDP_ColorVector *out ;
00332 static  QDP_ColorVector *in ; 
00333 
00334 
00335   static   QOP_info_t info; // wot for ????
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     //    invParam(invParam_),Mass(S_.getQuarkMass()), state(state_)
00347     invParam(invParam_),Mass(S_.getQuarkMass()), 
00348     state(state_.cast<AsqtadConnectStateBase>()) , M(S_.linOp(state_))
00349   {
00350     // Here is how to get at the gauge links: (Thanks Balint).
00351     // gauge not needed
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); // hack
00358 
00359     QDP_ColorMatrix **u_fat_qdp;
00360     u_chroma = u_fat ;
00361     u_fat_qdp = QDP_create_gauge_from_chroma(u_chroma) ;
00362     //    u_fat_qdp = QDP_create_gauge_from_chroma(u_fat) ;
00363 
00364     QDP_ColorMatrix **u_triple_qdp;
00365     u_chroma = u_triple ;
00366     u_triple_qdp = QDP_create_gauge_from_chroma(u_chroma) ;
00367     //    u_triple_qdp = QDP_create_gauge_from_chroma(u_triple) ;
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     // add staggered phases to the chroma gauge field
00389     multi1d<LatticeColorMatrix> u_chroma(Nd);
00390     // alpha comes from the StagPhases:: namespace
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   // setup the qdp 
00398   QOP_asqtad_coeffs_t coeffs;
00399   load_qop_asqtad_coeffs(&coeffs, 1.0) ;
00400   Real u0 = 1.0 ; 
00401 
00402   // ---- create the fat links ---------
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   // create the fat links 
00410   fla = QOP_asqtad_create_L_from_G(&info, &coeffs, gf);
00411 
00412   // remove the space for the gauge configuration
00413   // gf contains pointers to 4 components of uqdp,
00414   // so uqdp[i] do not need to be destroyed as well
00415   QOP_destroy_G(gf) ;
00416   free(uqdp) ;
00417 
00418 #endif
00419 
00420 }
00421 
00422   
00423   //! Destructor may not well be automatic
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   // convert "q_source" to in (qdp format)
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   // invert
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; // check norm convention
00482 
00483   // convert out to psi (qdp++ format)
00484   QOP_extract_V_to_qdp(out,qopout) ;
00485   convert_qdp_to_chroma(psi,out) ;
00486 
00487 
00488   // unscale the norm
00489 #if 0 
00490   exit(0) ; 
00491   Real mass_scale = 4.0 * Mass ;
00492   //  psi /= 4.0 * Mass ;
00493     T  tt;
00494     tt = psi ;
00495   psi = tt / mass_scale ; 
00496 #endif
00497 
00498   // Compute residual
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   //  QDP_start(argc, argv);
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   /** set up the level 3 code **/
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 

Generated on Sun Nov 22 04:28:49 2009 for CHROMA by  doxygen 1.4.7