inline_disco_eo_eigcg_w.cc

Go to the documentation of this file.
00001 
00002 // $Id: inline_disco_eo_eigcg_w.cc,v 3.3 2009/07/31 14:09:31 bjoo Exp $
00003 /*! \file
00004  * \brief Inline measurement 3pt_prop
00005  *
00006  * This uses eo-preconditioning on the noise vector side as well as
00007  * with the eig-cg vectors. NOTE THIS CODE DOES NOT WORK.          
00008  */
00009 #include <vector> 
00010 #include <map> 
00011 #include <qdp-lapack.h>
00012 #include <qdp_config.h>
00013 
00014 #include "handle.h"
00015 #include "meas/inline/hadron/inline_disco_eo_eigcg_w.h"
00016 #include "meas/inline/abs_inline_measurement_factory.h"
00017 #include "meas/smear/quark_smearing_factory.h"
00018 #include "meas/smear/quark_smearing_aggregate.h"
00019 #include "meas/smear/displacement.h"
00020 #include "meas/sources/source_smearing_aggregate.h"
00021 #include "meas/sources/source_smearing_factory.h"
00022 #include "meas/sources/dilutezN_source_const.h"
00023 #include "meas/sources/zN_src.h"
00024 #include "meas/sinks/sink_smearing_aggregate.h"
00025 #include "meas/sinks/sink_smearing_factory.h"
00026 #include "meas/hadron/barspinmat_w.h"
00027 #include "meas/hadron/baryon_operator_aggregate_w.h"
00028 #include "meas/hadron/baryon_operator_factory_w.h"
00029 #include "meas/hadron/barQll_w.h"
00030 #include "meas/hadron/dilution_scheme_aggregate.h"
00031 #include "meas/hadron/dilution_scheme_factory.h"
00032 #include "meas/glue/mesplq.h"
00033 #include "util/ft/sftmom.h"
00034 #include "util/info/proginfo.h"
00035 #include "meas/inline/make_xml_file.h"
00036 #include "util/info/unique_id.h"
00037 #include "util/ferm/transf.h"
00038 #include "meas/inline/io/named_objmap.h"
00039 
00040 #include "actions/ferm/fermacts/fermact_factory_w.h"
00041 #include "actions/ferm/fermacts/fermacts_aggregate_w.h"
00042 
00043 #include "eoprec_logdet_wilstype_fermact_w.h"
00044 #include "actions/ferm/linop/lgherm_w.h"
00045 
00046 #include "actions/ferm/fermacts/clover_fermact_params_w.h"
00047 #include "actions/ferm/fermacts/wilson_fermact_params_w.h"
00048 #include "actions/ferm/linop/linop_w.h"
00049 
00050 #include "util/ferm/key_val_db.h"
00051 
00052 namespace Chroma{
00053   namespace InlineDiscoEoEigCGEnv{ 
00054     namespace{
00055       AbsInlineMeasurement* createMeasurement(XMLReader& xml_in, 
00056                                               const std::string& path) 
00057       {
00058         return new InlineMeas(Params(xml_in, path));
00059       }
00060 
00061       //! Local registration flag
00062       bool registered = false;
00063     }
00064 
00065     const std::string name = "DISCO_EO_EIGCG";
00066 
00067     //! Register all the factories
00068     bool registerAll() 
00069     {
00070       bool success = true; 
00071       if (! registered)
00072       {
00073         //success &= BaryonOperatorEnv::registerAll();
00074         success &= TheInlineMeasurementFactory::Instance().registerObject(name, createMeasurement);
00075         registered = true;
00076       }
00077       return success;
00078     }
00079   
00080   // Reader for input parameters
00081   void read(XMLReader& xml, const string& path, Params::Param_t& param){
00082       XMLReader paramtop(xml, path);
00083       
00084       int version;
00085       read(paramtop, "version", version);
00086       
00087       switch (version) 
00088         {
00089         case 1:
00090           /************************************************************/
00091           read(paramtop,"max_path_length",param.max_path_length);
00092           read(paramtop,"p2_max",param.p2_max);
00093           read(paramtop,"mass_label",param.mass_label);
00094           param.chi = readXMLArrayGroup(paramtop, "Quarks", "DilutionType");
00095           param.action = readXMLGroup(paramtop, "FermionAction","FermAct");
00096           
00097           break;
00098           
00099         default :
00100           /**************************************************************/
00101 
00102           QDPIO::cerr << "Input parameter version " << version << " unsupported." << endl;
00103           QDP_abort(1);
00104         }
00105     }
00106 
00107     // Writer for input parameters
00108     void write(XMLWriter& xml, const string& path, const Params::Param_t& param){
00109       push(xml, path);
00110       
00111       int version = 1;
00112       
00113       write(xml, "version", version);
00114 
00115       write(xml,"max_path_length",param.max_path_length);
00116       write(xml,"p2_max",param.p2_max);
00117       write(xml,"mass_label",param.mass_label);
00118       push(xml,"FermionAction");
00119       xml<<param.action.xml ;
00120       pop(xml);
00121       push(xml,"Quarks");
00122       for( int t(0);t<param.chi.size();t++){
00123         push(xml,"elem");
00124         xml<<param.chi[t].xml;
00125         pop(xml);
00126       }
00127       pop(xml);
00128       
00129       pop(xml); // final pop
00130     }
00131     
00132     //! Gauge field parameters
00133     void read(XMLReader& xml, const string& path, Params::NamedObject_t& input)
00134     {
00135       XMLReader inputtop(xml, path);
00136       
00137       read(inputtop, "gauge_id"   , input.gauge_id   ) ;
00138       // If no file is included, then we will turn off the eig_cg part (ie, use 0 vectors)
00139       if ( inputtop.count("evecs_file")!=0 )
00140         read(inputtop, "evecs_file" , input.evecs_file ) ;
00141       else
00142         input.evecs_file="";
00143         
00144       read(inputtop, "op_db_file" , input.op_db_file ) ;
00145     }
00146     
00147     //! Gauge field parameters
00148     void write(XMLWriter& xml, const string& path, const Params::NamedObject_t& input){
00149       push(xml, path);
00150       
00151       write(xml, "gauge_id"   , input.gauge_id   );
00152       write(xml, "evecs_file" , input.evecs_file );
00153       write(xml, "op_db_file" , input.op_db_file );
00154       pop(xml);
00155     }
00156     
00157     
00158     // Param stuff
00159     Params::Params(){ 
00160       frequency = 0;
00161     }
00162     
00163     Params::Params(XMLReader& xml_in, const std::string& path) 
00164     {
00165       try 
00166         {
00167           XMLReader paramtop(xml_in, path);
00168           
00169           if (paramtop.count("Frequency") == 1)
00170             read(paramtop, "Frequency", frequency);
00171           else
00172             frequency = 1;
00173           
00174           // Read program parameters
00175           read(paramtop, "Param", param);
00176           
00177           // Read in the output propagator/source configuration info
00178           read(paramtop, "NamedObject", named_obj);
00179           
00180           // Possible alternate XML file pattern
00181           if (paramtop.count("xml_file") != 0) 
00182             {
00183               read(paramtop, "xml_file", xml_file);
00184             }
00185         }
00186       catch(const std::string& e) 
00187         {
00188           QDPIO::cerr << __func__ << ": Caught Exception reading XML: " << e << endl;
00189           QDP_abort(1);
00190         }
00191     }
00192 
00193 
00194     void Params::write(XMLWriter& xml_out, const std::string& path) 
00195     {
00196       push(xml_out, path);
00197       
00198       // Parameters for source construction
00199       InlineDiscoEoEigCGEnv::write(xml_out, "Param", param);
00200       
00201       // Write out the output propagator/source configuration info
00202       InlineDiscoEoEigCGEnv::write(xml_out, "NamedObject", named_obj);
00203 
00204       pop(xml_out);
00205     }
00206 
00207     
00208     //! Meson operator     
00209     struct KeyOperator_t
00210     {
00211       multi1d<short int> mom     ; /*!< D-1 momentum of this operator */
00212       unsigned short int t_slice ; /*!< Meson operator time slice */
00213       multi1d<short int> disp    ; /*!< Displacement dirs of quark (right)*/
00214       
00215       KeyOperator_t(){
00216         mom.resize(Nd-1);
00217       }
00218     };
00219     
00220     bool operator<(const KeyOperator_t& a, const KeyOperator_t& b){
00221       return ((a.t_slice<b.t_slice)||(a.mom<b.mom)||(a.disp<b.disp));
00222     }
00223 
00224     std::ostream& operator<<(std::ostream& os, const KeyOperator_t& d)
00225     {
00226       os << "KeyOperator_t:"
00227          << " t_slice = " << d.t_slice
00228          << ", disp = ";
00229       for (int i=0; i<d.disp.size();i++)
00230         os << d.disp[i] << " " ;
00231       
00232       os << ", mom = ";
00233       for (int i=0; i<d.mom.size();i++)
00234         os << d.mom[i] << " " ;
00235 
00236       os << std::endl;
00237 
00238       return os;
00239     }
00240 
00241     class ValOperator_t{
00242     public:
00243       multi1d<ComplexD> op ;  
00244       ValOperator_t(){op.resize(Ns*Ns);} // Here go the 16 gamma matrices
00245       ~ValOperator_t(){}
00246     } ;
00247 
00248     //-------------------------------------------------------------------------                            
00249     //! stream IO                                                                                          
00250     std::ostream& operator<<(std::ostream& os, const ValOperator_t& d)
00251     {
00252       os << "ValOperator_t:\n";
00253       for (int i=0; i<d.op.size();i++)
00254         os <<"     gamma["<<i<<"] = "<< d.op[i] << endl ;
00255       
00256       return os;
00257     }
00258     
00259     struct KeyVal_t{
00260       SerialDBKey <KeyOperator_t> k ;
00261       SerialDBData<ValOperator_t> v ;
00262     };
00263 
00264     //! KeyOperator reader    
00265     void read(BinaryReader& bin, KeyOperator_t& d){
00266       read(bin,d.t_slice);
00267       unsigned short int n ;
00268       read(bin,n);
00269       d.disp.resize(n); 
00270       read(bin,d.disp);
00271       d.mom.resize(Nd-1) ;
00272       read(bin,d.mom);
00273     }
00274     //! KeyOperator writer
00275     void write(BinaryWriter& bin, KeyOperator_t& d){
00276       write(bin,d.t_slice);
00277       unsigned short int n ;
00278       n = d.disp.size();
00279       write(bin,n);
00280       write(bin,d.disp);
00281       write(bin,d.mom);
00282     }
00283 
00284     //! ValOperator reader    
00285     void read(BinaryReader& bin, ValOperator_t& d){
00286       d.op.resize(Ns*Ns);
00287       read(bin,d.op);
00288     }
00289     //! ValOperator writer
00290     void write(BinaryWriter& bin, ValOperator_t& d){
00291       write(bin,d.op);
00292     }
00293 
00294     namespace{
00295       StandardOutputStream& operator<<(StandardOutputStream& os, const multi1d<short int>& d){
00296         if (d.size() > 0){
00297           os << d[0]; 
00298           for(int i=1; i < d.size(); i++)
00299             os << " " << d[i];
00300         }
00301         return os;
00302       }
00303     }
00304 
00305     typedef LatticeFermion               T;
00306     typedef multi1d<LatticeColorMatrix>  P;
00307     typedef multi1d<LatticeColorMatrix>  Q;
00308 
00309     Handle<EvenOddPrecLinearOperator<T,P,Q> > 
00310     createOddOdd_Op( const Params::Param_t& param, const P& u){     
00311       //
00312       // Initialize fermion action
00313       //
00314       std::istringstream  xml_s(param.action.xml);
00315       XMLReader  fermacttop(xml_s);
00316       QDPIO::cout << "FermAct = " << param.action.id << endl;
00317       //
00318       // Try the factories
00319       //
00320       Handle< FermState< T,P,Q> > state ;
00321       try{
00322           QDPIO::cout << "Try the various Wilson fermion factories" << endl;
00323           // Generic Wilson-Type stuff
00324           Handle< FermionAction< T,P,Q > >
00325             Sf(TheFermionActionFactory::Instance().createObject(param.action.id,
00326                                                                 fermacttop,
00327                                                                 param.action.path));
00328           state = Sf->createState(u);//got the state
00329           QDPIO::cout << "Suitable factory found: compute the trace quark prop"<<endl;
00330       }
00331       catch (const std::string& e){
00332         QDPIO::cout << name 
00333                     << ": caught exception instantiating the action: " << e << endl;
00334       }
00335       
00336       // Now need to construct the operator
00337       // this seems tricky and maybe there is a better way... (Robert-Balint help!)
00338       // We only work with Wilson and Clover Wilson fermions so check the following 2
00339       // For the moment we restrict to EO preconditioned only
00340       
00341       //this is the Odd-Odd piece
00342       Handle<EvenOddPrecLinearOperator<T,P,Q> > Doo ;
00343       if(param.action.id == "WILSON"){
00344         WilsonFermActParams wp(fermacttop,param.action.path);
00345         return new EvenOddPrecWilsonLinOp(state,wp.Mass,wp.anisoParam ) ;
00346       }
00347       else if(param.action.id == "CLOVER"){
00348         CloverFermActParams cp(fermacttop,param.action.path);
00349         return new EvenOddPrecCloverLinOp(state,cp) ;
00350       }
00351       else{
00352         QDPIO::cout<<name<<" : Tough luck dude! No code for you..."<<endl ;
00353         QDP_abort(1);
00354       }
00355       return NULL ;
00356     }
00357 
00358     struct CholeskyFactors{
00359       multi1d<Real>    evals ;
00360       multi1d<Complex> H     ;
00361       multi1d<Complex> HU    ;
00362       int              ldh   ;
00363       int              Nvec  ;
00364     } ;
00365 
00366     void do_disco(map< KeyOperator_t, ValOperator_t >& db,
00367                   const LatticeFermion& qbar,
00368                   const LatticeFermion& q,
00369                   const SftMom& p,
00370                   const int& t, 
00371                   const Subset& trb,
00372                   const multi1d<short int>& path,
00373                   const int& max_path_length ){
00374       QDPIO::cout<<" Computing Operator with path length "<<path.size()
00375                  <<" on timeslice "<<t<<".   Path: "<<path <<endl;
00376       /**
00377          This do_disco routine should not be called, I don't think it's ever needed...
00378       
00379        **/
00380       ValOperator_t val ;
00381       KeyOperator_t key ;
00382       pair<KeyOperator_t, ValOperator_t> kv ; 
00383       kv.first.t_slice = t ;
00384       if(path.size()==0){
00385         kv.first.disp.resize(1);
00386         kv.first.disp[0] = 0 ;
00387       }
00388       else
00389         kv.first.disp = path ;
00390       
00391       multi1d< multi1d<ComplexD> > foo(p.numMom()) ;
00392       for (int m(0); m < p.numMom(); m++)
00393         foo[m].resize(Ns*Ns);
00394       for(int g(0);g<Ns*Ns;g++){
00395         LatticeComplex cc = localInnerProduct(qbar,Gamma(g)*q);
00396         for (int m(0); m < p.numMom(); m++){
00397           // trb is the set of even/odd sites on timeslice t
00398           foo[m][g] = sum(p[m]*cc,trb);
00399         }
00400       }
00401       for (int m(0); m < p.numMom(); m++){
00402         for(int i(0);i<(Nd-1);i++)
00403           kv.first.mom[i] = p.numToMom(m)[i] ;
00404         
00405         kv.second.op = foo[m];
00406         pair<map< KeyOperator_t, ValOperator_t >::iterator, bool> itbo;
00407         
00408         itbo = db.insert(kv);
00409         if( itbo.second ){
00410           QDPIO::cout<<"Inserting new entry in map\n";
00411         }
00412         else{ // if insert fails, key already exists, so add result
00413           for(int i(0);i<kv.second.op.size();i++)
00414             itbo.first->second.op[i] += kv.second.op[i] ;
00415         }
00416       }//m 
00417       
00418       if(path.size()<max_path_length){
00419         QDPIO::cout<<" attempt to add new path. "
00420                    <<" current path length is : "<<path.size();
00421         multi1d<short int> new_path(path.size()+1);
00422         QDPIO::cout<<" new path length is : "<<new_path.size()<<endl;
00423         for(int i(0);i<path.size();i++)
00424           new_path[i] = path[i] ;
00425         for(int sign(-1);sign<2;sign+=2)
00426           for(int mu(0);mu<Nd;mu++){
00427             new_path[path.size()]= sign*(mu+1) ;
00428             //skip back tracking 
00429             bool back_track=false ;
00430             if(path.size()>0)
00431               if(path[path.size()-1] == -new_path[path.size()])
00432                 back_track=true;
00433             if(!back_track){
00434               QDPIO::cout<<" Added path: "<<new_path<<endl;
00435               LatticeFermion q_mu ;
00436               if(sign>0)
00437                 q_mu = shift(q, FORWARD, mu);
00438               else
00439                 q_mu = shift(q, BACKWARD, mu);
00440 
00441               do_disco(db, qbar, q_mu, p, t, trb,  new_path, max_path_length);
00442             } // skip backtracking
00443           } // mu
00444       }// path.size loop
00445       
00446     }// do_disco
00447 
00448     void do_disco(map< KeyOperator_t, ValOperator_t >& db,
00449                   const LatticeFermion& qbar,
00450                   const LatticeFermion& q,
00451                   const Handle<EvenOddPrecLinearOperator<T,P,Q> >& Doo,
00452                   const SftMom& p,
00453                   const int& t, 
00454                   const Subset& trb,
00455                   const multi1d<short int>& path,
00456                   const int& max_path_length ){
00457       QDPIO::cout<<" Computing Operator with path length "<<path.size()
00458                  <<" on timeslice "<<t<<".   Path: "<<path <<endl;
00459       
00460       /** This version of do_disco is the one we call 
00461           
00462       Currently we have editted this so as to put the timeslice and phase factor
00463       on the correct part for the "even" sum, so right now this code is not terribly 
00464       efficient. Work on optimizing this all later.      
00465 
00466       **/
00467       
00468       ValOperator_t val ;
00469       KeyOperator_t key ;
00470       pair<KeyOperator_t, ValOperator_t> kv ; 
00471       kv.first.t_slice = t ;
00472       if(path.size()==0){
00473         kv.first.disp.resize(1);
00474         kv.first.disp[0] = 0 ;
00475       }
00476       else
00477         kv.first.disp = path ;
00478 
00479       multi1d< multi1d<ComplexD> > foo(p.numMom()) ;
00480       for (int m(0); m < p.numMom(); m++)
00481         foo[m].resize(Ns*Ns);
00482 
00483       // First do the odd sites, and put in foo.
00484       for(int g(0);g<Ns*Ns;g++){
00485         LatticeComplex cc = localInnerProduct(qbar,Gamma(g)*q);
00486         for (int m(0); m < p.numMom(); m++){
00487           // trb is the set of odd sites on timeslice t
00488           foo[m][g] = sum(p[m]*cc,trb);
00489         }
00490       }
00491       
00492       Set t0set;
00493       t0set.make(TimeSliceFunc(Nd-1));// 3 is decay dir....need to change this later.
00494       
00495       // Now we have to do the even sites
00496       LatticeFermion qtmp  = zero ;
00497       LatticeFermion qbar2 = zero ;
00498       Doo->evenOddLinOp(qtmp,q,PLUS);
00499       Doo->evenEvenInvLinOp(qbar2,qtmp,PLUS);                                            
00500       for(int g(0);g<Ns*Ns;g++){
00501         for (int m(0); m < p.numMom(); m++){
00502           LatticeFermion q2 = zero ;
00503           LatticeFermion chi = zero ;
00504           qtmp = zero ;
00505           q2[t0set[t]] = p[m]*(Gamma(g)*qbar2);//rhs should only set the t0 terms non-zero...
00506           Doo->evenEvenInvLinOp(qtmp,q2,PLUS);
00507           Doo->oddEvenLinOp(chi,qtmp,PLUS);                                                   
00508           foo[m][g] += innerProduct(qbar,chi);
00509         }
00510       }
00511       
00512       for (int m(0); m < p.numMom(); m++){
00513         for(int i(0);i<(Nd-1);i++)
00514           kv.first.mom[i] = p.numToMom(m)[i] ;
00515         
00516         kv.second.op = foo[m];
00517         pair<map< KeyOperator_t, ValOperator_t >::iterator, bool> itbo;
00518         
00519         itbo = db.insert(kv);
00520         if( itbo.second ){
00521           QDPIO::cout<<"Inserting new entry in map\n";
00522         }
00523         else{ // if insert fails, key already exists, so add result
00524           for(int i(0);i<kv.second.op.size();i++)
00525             itbo.first->second.op[i] += kv.second.op[i] ;
00526         }
00527       }//m 
00528       
00529       if(path.size()<max_path_length){
00530         QDPIO::cout<<" attempt to add new path. "
00531                    <<" current path length is : "<<path.size();
00532         multi1d<short int> new_path(path.size()+1);
00533         QDPIO::cout<<" new path length is : "<<new_path.size()<<endl;
00534         for(int i(0);i<path.size();i++)
00535           new_path[i] = path[i] ;
00536         for(int sign(-1);sign<2;sign+=2)
00537           for(int mu(0);mu<Nd;mu++){
00538             new_path[path.size()]= sign*(mu+1) ;
00539             //skip back tracking 
00540             bool back_track=false ;
00541             if(path.size()>0)
00542               if(path[path.size()-1] == -new_path[path.size()])
00543                 back_track=true;
00544             if(!back_track){
00545               QDPIO::cout<<" Added path: "<<new_path<<endl;
00546               LatticeFermion q_mu ;
00547               if(sign>0)
00548                 q_mu = shift(q, FORWARD, mu);
00549               else
00550                 q_mu = shift(q, BACKWARD, mu);
00551 
00552               do_disco(db, qbar, q_mu, Doo, p, t, trb,  new_path, max_path_length);
00553             } // skip backtracking
00554           } // mu
00555       }// path.size loop
00556       
00557     }// do_disco
00558 
00559     void do_disco(map< KeyOperator_t, ValOperator_t >& db,
00560                   const Params::Param_t& param,
00561                   const P& u,
00562                   const SftMom& p,
00563                   const int& t, 
00564                   const Subset& trb,
00565                   const multi1d<short int>& path){
00566       QDPIO::cout<<" Computing Operator with path length "<<path.size()
00567                  <<" on timeslice "<<t<<".   Path: "<<path <<endl;
00568       
00569       int max_path_length = param.max_path_length;
00570       ValOperator_t val ;
00571       KeyOperator_t key ;
00572       pair<KeyOperator_t, ValOperator_t> kv ; 
00573       kv.first.t_slice = t ;
00574       if(path.size()==0){
00575         kv.first.disp.resize(1);
00576         kv.first.disp[0] = 0 ;
00577       }
00578       else
00579         kv.first.disp = path ;
00580       
00581       Handle<EvenOddPrecLinearOperator<T,P,Q> > Doo = createOddOdd_Op(param,u);
00582       
00583       multi1d< multi1d<ComplexD> > foo(p.numMom()) ;
00584       for (int m(0); m < p.numMom(); m++){
00585         foo[m].resize(Ns*Ns);
00586         for (int g(0); g<Ns*Ns;g++){
00587           foo[m][g] = 0.0;
00588         }
00589       }
00590       for(int g(0);g<Ns*Ns;g++){
00591         for(int col=0;col<3;col++){
00592           for(int sp=0;sp<4;sp++){
00593             Fermion tt = zero ;
00594             ColorVector cv = zero ;
00595             Complex z = cmplx(Real(1.0),0.0) ;
00596             pokeColor(cv,z,col);
00597             pokeSpin(tt,cv,sp);
00598             LatticeFermion V = tt ;
00599             for (int m(0); m < p.numMom(); m++){
00600               //only on even sites
00601               LatticeFermion DV = zero;
00602               Doo->evenEvenInvLinOp(DV,V,PLUS);
00603               foo[m][g] += sum(p[m]*localInnerProduct(V,Gamma(g)*DV),trb);
00604             }//m
00605           }//spin
00606         }//col
00607       }//g
00608 
00609       for (int m(0); m < p.numMom(); m++){
00610         for(int i(0);i<(Nd-1);i++)
00611           kv.first.mom[i] = p.numToMom(m)[i] ;
00612         
00613         kv.second.op = foo[m];
00614         pair<map< KeyOperator_t, ValOperator_t >::iterator, bool> itbo;
00615         
00616         itbo = db.insert(kv);
00617         if( itbo.second ){
00618           QDPIO::cout<<"Inserting new entry in map\n";
00619         }
00620         else{ // if insert fails, key already exists, so add result
00621           for(int i(0);i<kv.second.op.size();i++)
00622             itbo.first->second.op[i] += kv.second.op[i] ;
00623         }
00624       }//m 
00625       
00626     }// do_disco
00627 
00628     void do_disco(map< KeyOperator_t, ValOperator_t >& db,
00629                   CholeskyFactors Clsk , 
00630                   multi1d<LatticeFermion>& vec,
00631                   const Params::Param_t& param, 
00632                   const Handle<EvenOddPrecLinearOperator<T,P,Q> >& Doo,
00633                   const P& u,
00634                   const int& t,
00635                   const Subset& trb, 
00636                   const SftMom& p,
00637                   const multi1d<short int>& path){
00638 
00639       QDPIO::cout<<" Computing Operator with path length "<<path.size()
00640                  <<" on timeslice "<<t<<".   Path: "<<path <<endl;
00641       int max_path_length = param.max_path_length;
00642       
00643       ValOperator_t val ;
00644       KeyOperator_t key ;
00645       pair<KeyOperator_t, ValOperator_t> kv ; 
00646 
00647       kv.first.t_slice = t ;
00648       if(path.size()==0){
00649         kv.first.disp.resize(1);
00650         kv.first.disp[0] = 0 ;
00651       }
00652       else
00653         kv.first.disp = path ;
00654       
00655       int ldb = vec.size();
00656       int info;
00657       char U = 'U';
00658       int Nrhs = ldb; // Because we have no dilution vectors, but rhs's are made of EigCG vecs...
00659       multi2d<Complex> B(Nrhs,ldb);
00660       multi1d< multi1d<LatticeFermion> > DDvec(ldb);
00661       // Zero out the fermions
00662       for(int i(0); i<ldb;i++){
00663         DDvec[i].resize(Ns*Ns);
00664         DDvec[i] = zero;
00665       }
00666       cout<<"We've initialized DDvec!\n";
00667 
00668       for(int i(0); i<ldb;i++){
00669         LatticeFermion qtmp  = zero ;
00670         LatticeFermion qtmp2 = zero ;
00671         LatticeFermion qtmp3 = zero ;
00672         Doo->evenOddLinOp(qtmp,vec[i],PLUS);
00673         Doo->evenEvenInvLinOp(qtmp2,qtmp,PLUS);
00674         for(int g(0);g<Ns*Ns;g++){
00675           Doo->evenEvenInvLinOp(qtmp3,Gamma(g)*qtmp2,PLUS);
00676           qtmp = zero;
00677           qtmp2 = zero;
00678           Doo->oddEvenLinOp(qtmp,qtmp3,PLUS);
00679           Doo->oddOddLinOp(qtmp2,qtmp,MINUS);
00680           qtmp = zero;
00681           Doo->oddOddLinOp(qtmp,Gamma(g)*vec[i],MINUS);
00682           // I think this could run into memory problems with too many vectors
00683           DDvec[i][g] = qtmp + qtmp2;
00684         }
00685       }
00686 
00687       multi1d< multi1d<ComplexD> > foo(p.numMom()) ;
00688       for (int m(0); m < p.numMom(); m++){
00689         foo[m].resize(Ns*Ns);
00690         foo[m] = zero;
00691       }
00692       // Okay, this is probably inefficient, b/c we are doing some things multiple times...
00693       for(int g(0);g<Ns*Ns;g++){
00694         for (int m(0); m < p.numMom(); m++){
00695           for (int i(0); i<ldb;i++){
00696             for (int j(0); j<ldb;j++){
00697               //              LatticeComplex cc1 = localInnerProduct(Svec[j],Gamma(g)*vec[i]);
00698               LatticeComplex cc2 = localInnerProduct(vec[j],DDvec[i][g]);
00699               B[i][j] = sum(p[m]*cc2,trb) ;
00700             }//j
00701           }//i 
00702 
00703 #if BASE_PRECISION == 32
00704           int r = QDPLapack::cpotrs(U, Clsk.Nvec, Nrhs, Clsk.HU, Clsk.ldh, B, ldb, info);
00705 #else
00706           int r = QDPLapack::zpotrs(U, Clsk.Nvec, Nrhs, Clsk.HU, Clsk.ldh, B, ldb, info);
00707 #endif
00708           // and at this point, B is H^-1 Vdag Sdag gamma V, so
00709           // For debugging purposes, both r and info should be zero...
00710           QDPIO::cout<<"do_disco cpotrs r = "<<r<<endl;
00711           QDPIO::cout<<"do_disco cpotrs info = "<<info<<endl;
00712 
00713           //      foo[m][g] = 0.0;
00714           for (int i(0); i<ldb;i++){
00715             foo[m][g] += ComplexD(B[i][i]);// Trace over last set of indices
00716           }
00717         }//m
00718       }//g
00719       for (int m(0); m < p.numMom(); m++){
00720         for(int i(0);i<(Nd-1);i++)
00721           kv.first.mom[i] = p.numToMom(m)[i] ;
00722         
00723         kv.second.op = foo[m];
00724 
00725         pair<map< KeyOperator_t, ValOperator_t >::iterator, bool> itbo;
00726         
00727         itbo = db.insert(kv);
00728         if( !(itbo.second) ){  // if insert fails, key already exists, so add result
00729           for(int i(0);i<kv.second.op.size();i++)
00730             itbo.first->second.op[i] += kv.second.op[i] ;
00731         }
00732         else
00733           QDPIO::cout<<"Inserting new entry in map\n";
00734       }
00735 
00736       if(path.size()<max_path_length){
00737         QDPIO::cout<<" attempt to add new path. "
00738                    <<" current path length is : "<<path.size();
00739         multi1d<short int> new_path(path.size()+1);
00740         QDPIO::cout<<" new path length is : "<<new_path.size()<<endl;
00741         for(int i(0);i<path.size();i++)
00742           new_path[i] = path[i] ;
00743         for(int sign(-1);sign<2;sign+=2)
00744           for(int mu(0);mu<Nd;mu++){
00745             new_path[path.size()]= sign*(mu+1) ;
00746             //skip back tracking 
00747             bool back_track=false ;
00748             if(path.size()>0)
00749               if(path[path.size()-1] == -new_path[path.size()])
00750                 back_track=true;
00751             if(!back_track){
00752               QDPIO::cout<<" Added path: "<<new_path<<endl;
00753               multi1d<LatticeFermion> vec_mu(vec.size()) ;
00754               for(int j(0);j<vec.size();j++){
00755                 if(sign>0)
00756                   vec_mu[j] = shift(vec[j], FORWARD, mu);
00757                 else
00758                   vec_mu[j] = shift(vec[j], BACKWARD, mu);
00759               }
00760               do_disco(db, Clsk , vec_mu, param, Doo, u, t, trb, p, new_path);
00761             } // skip backtracking
00762           } // mu
00763       }// path.size loop
00764     }// do_disco
00765     
00766 
00767     void ReadOPTEigCGVecs(multi1d<LatticeFermion>& vec,
00768                             CholeskyFactors& Clsk, 
00769                             const string& evecs_file)
00770     {
00771       QDPIO::cout<<name<<" : Reading vecs from "
00772                  << evecs_file <<endl ;
00773       StopWatch swatch;
00774       swatch.reset();
00775       swatch.start();
00776       
00777       int Nvecs,ldh ;
00778       // File XML                                      
00779       XMLReader file_xml;
00780       // Open file
00781       QDPFileReader to(file_xml,evecs_file,QDPIO_SERIAL);
00782       read(file_xml, "/OptEigInfo/ncurEvals", Nvecs);
00783       read(file_xml, "/OptEigInfo/ldh", ldh);
00784       // Added Nvecs and ldh to the Cholesky structure for later...
00785       Clsk.Nvec = Nvecs;
00786       Clsk.ldh = ldh;
00787       vec.resize(Nvecs);
00788       Clsk.evals.resize(ldh);
00789       Clsk.H.resize(ldh*ldh);
00790       Clsk.HU.resize(ldh*ldh);
00791 
00792       for(int v(0);v<Nvecs;v++){
00793         XMLReader record_xml;
00794         read(to, record_xml, vec[v]);
00795       }
00796       
00797       XMLReader record_xml;
00798       read(to, record_xml, Clsk.evals);
00799       read(to, record_xml, Clsk.H);
00800       read(to, record_xml, Clsk.HU);
00801       swatch.stop();
00802       QDPIO::cout<<name<<" : Time to read vecs= "
00803                  << swatch.getTimeInSeconds() <<" secs "<<endl ;
00804     }
00805 
00806     // PRchi returns chitilde = (1 - V Hinv Vdag Sdag S)chi given
00807     // an input chi vector, and of course the vectors and H. 
00808     void PRchi(multi1d<multi1d< multi1d<LatticeFermion> > >& quarkstilde,
00809                const multi1d< Handle< DilutionScheme<LatticeFermion> > >& quarks,
00810                Handle<EvenOddPrecLinearOperator<T,P,Q> >& Doo,
00811                CholeskyFactors Clsk , multi1d<LatticeFermion>& vec,
00812                const Params::Param_t& param, const P& u){
00813       char U = 'U';
00814       int info;
00815 
00816       int ldb = vec.size();//This is the offset that will for now be the size of each vector
00817 
00818       Set timerb;
00819       timerb.make(TimeSliceRBFunc(3));
00820 
00821       // Now we have to create the Sdag * S * quarks object to put into B
00822       for(int n(0);n<quarks.size();n++){
00823         for (int it(0) ; it < quarks[n]->getNumTimeSlices() ; ++it){
00824           int t = quarks[n]->getT0(it) ;
00825           int Nrhs = quarks[n]->getDilSize(it) ;
00826           multi2d<Complex> B(Nrhs, ldb);
00827           for(int i(0); i<ldb;i++){
00828             for(int j = 0 ; j <  Nrhs ; j++){
00829               /**
00830                  Here, we are calculating 
00831                    Sdag S chi
00832                  where chi (the solution) is Sinv eta, and eta is the noise vector (the source)
00833                  Thus, we can save time by using the source, and calculate
00834                    Sdag eta,
00835                  and that's what is being done here
00836                **/
00837               LatticeFermion qsrc     = quarks[n]->dilutedSource(it,j);
00838               LatticeFermion SdagSchi = zero ;
00839               Doo->oddOddLinOp(SdagSchi,qsrc,MINUS); 
00840               // Sum over (odd) lattice sites, so we return a complex number for B
00841               // SHOULDN'T THIS BE ONLY SITES THAT INCLUDE THE TIMESLICE WE'RE ON?
00842               //              B[j][i] = sum(localInnerProduct(vec[i],SdagSchi),rb[1]);
00843               B[j][i] = sum(localInnerProduct(vec[i],SdagSchi),timerb[2*t+1]);
00844             }
00845           }
00846 
00847           // This could be better done.
00848 #if BASE_PRECISION == 32
00849           int r = QDPLapack::cpotrs(U, Clsk.Nvec, Nrhs, Clsk.HU, Clsk.ldh, B, ldb, info);
00850 #else
00851           int r = QDPLapack::zpotrs(U, Clsk.Nvec, Nrhs, Clsk.HU, Clsk.ldh, B, ldb, info);
00852 #endif
00853           QDPIO::cout<<"PRchi cpotrs r = "<<r<<endl;
00854           QDPIO::cout<<"PRchi cpotrs info = "<<info<<endl;
00855 
00856           for(int j = 0 ; j <  Nrhs ; j++){
00857             LatticeFermion vB = zero; //B[j][0]*vec[0];
00858             LatticeFermion q     = quarks[n]->dilutedSolution(it,j);
00859             for(int i(0); i<ldb;i++)
00860               vB += B[j][i]*vec[i];
00861             quarkstilde[n][it][j] = q - vB;
00862             cout<<"Norm of PRchi: "<<norm2(quarkstilde[n][it][j])<<endl;
00863           }
00864         }
00865       }
00866     }// End of PRchi call...
00867     
00868     /**
00869        This version is called if we have no EigCG vectors, so PR = 1
00870      **/
00871     void PRchi(multi1d<multi1d< multi1d<LatticeFermion> > >& quarkstilde,
00872                multi1d< Handle< DilutionScheme<LatticeFermion> > >& quarks){
00873       
00874       for(int n(0);n<quarks.size();n++){
00875         for (int it(0) ; it < quarks[n]->getNumTimeSlices() ; it++){
00876           for (int j(0) ; j < quarks[n]->getDilSize(it) ; j++){
00877             quarkstilde[n][it][j] = quarks[n]->dilutedSolution(it,j);
00878           }
00879         }
00880       }
00881     }// End of PRchi call...
00882     
00883   //--------------------------------------------------------------
00884   // Function call
00885   //  void 
00886   //InlineDiscoEigCG::operator()(unsigned long update_no,
00887   //                            XMLWriter& xml_out) 
00888     void InlineMeas::operator()(unsigned long update_no,
00889                                 XMLWriter& xml_out) 
00890     {
00891       // If xml file not empty, then use alternate
00892       if (params.xml_file != ""){
00893         string xml_file = makeXMLFileName(params.xml_file, update_no);
00894         
00895         push(xml_out, "discoEigCG");
00896         write(xml_out, "update_no", update_no);
00897         write(xml_out, "xml_file", xml_file);
00898         pop(xml_out);
00899         
00900         XMLFileWriter xml(xml_file);
00901         func(update_no, xml);
00902       }
00903       else{
00904         func(update_no, xml_out);
00905       }
00906     }
00907     
00908     
00909     // Function call
00910     //void 
00911     //InlineDiscoEigCG::func(unsigned long update_no,
00912     //                    XMLWriter& xml_out) 
00913     void InlineMeas::func(unsigned long update_no,
00914                           XMLWriter& xml_out) 
00915     {
00916       START_CODE();
00917       
00918       StopWatch snoop;
00919       snoop.reset();
00920       snoop.start();
00921       
00922       /*** Stuff to set up everything! ***/
00923       // Test and grab a reference to the gauge field
00924       XMLBufferWriter gauge_xml;
00925       try
00926         {
00927           TheNamedObjMap::Instance().getData< multi1d<LatticeColorMatrix> >(params.named_obj.gauge_id);
00928           TheNamedObjMap::Instance().get(params.named_obj.gauge_id).getRecordXML(gauge_xml);
00929         }
00930       catch( std::bad_cast ) 
00931         {
00932           QDPIO::cerr << InlineDiscoEoEigCGEnv::name << ": caught dynamic cast error" 
00933                       << endl;
00934           QDP_abort(1);
00935         }
00936       catch (const string& e) 
00937         {
00938           QDPIO::cerr << name << ": map call failed: " << e 
00939                       << endl;
00940           QDP_abort(1);
00941         }
00942       const multi1d<LatticeColorMatrix>& u = 
00943         TheNamedObjMap::Instance().getData< multi1d<LatticeColorMatrix> >(params.named_obj.gauge_id);
00944       
00945       push(xml_out, "discoEigCG");
00946       write(xml_out, "update_no", update_no);
00947       
00948       QDPIO::cout << name << ": Disconnected diagrams with eigCG vectors" << endl;
00949       
00950       proginfo(xml_out);    // Print out basic program info
00951       
00952       // Write out the input
00953       params.write(xml_out, "Input");
00954       
00955       // Write out the config info
00956       write(xml_out, "Config_info", gauge_xml);
00957       
00958       push(xml_out, "Output_version");
00959       write(xml_out, "out_version", 1);
00960       pop(xml_out);
00961       
00962       // First calculate some gauge invariant observables just for info.
00963       // This is really cheap.
00964       MesPlq(xml_out, "Observables", u);
00965       
00966       // Save current seed
00967       Seed ran_seed;
00968       QDP::RNG::savern(ran_seed);
00969       
00970       //
00971       // Read the source and solutions
00972       //
00973       StopWatch swatch;
00974       swatch.reset();
00975       swatch.start();
00976       
00977       int N_quarks = params.param.chi.size() ;
00978 
00979       multi1d< Handle< DilutionScheme<LatticeFermion> > > quarks(N_quarks);
00980 
00981       try{
00982         // Loop over quark dilutions
00983         for(int n(0); n < params.param.chi.size(); n++){
00984           const GroupXML_t& dil_xml = params.param.chi[n];
00985           std::istringstream  xml_d(dil_xml.xml);
00986           XMLReader  diltop(xml_d);
00987           QDPIO::cout << "Dilution type = " << dil_xml.id << endl;
00988           quarks[n] = 
00989             TheFermDilutionSchemeFactory::Instance().createObject(dil_xml.id, 
00990                                                                   diltop, 
00991                                                                   dil_xml.path);
00992         }
00993       }
00994       catch(const std::string& e){
00995         QDPIO::cerr << name << ": Caught Exception constructing dilution scheme: " << e << endl;
00996         QDP_abort(1);
00997       }
00998       
00999       
01000       //-------------------------------------------------------------------
01001       //Sanity checks   
01002 
01003       //Another Sanity check, the three quarks must all be 
01004       //inverted on the same cfg
01005       for (int n = 1 ; n < N_quarks ; n++){
01006         if (quarks[0]->getCfgInfo() != quarks[n]->getCfgInfo()){
01007           QDPIO::cerr << name << " : Quarks do not contain the same cfg info";
01008           QDPIO::cerr << ", quark "<< n << endl;
01009           QDP_abort(1);
01010         }               
01011       }
01012 
01013       //Also ensure that the cfg on which the inversions were performed 
01014       //is the same as the cfg that we are using
01015       { 
01016         std::string cfgInfo; 
01017         
01018         //Really ugly way of doing this (Robert Heeeelp!!)
01019         XMLBufferWriter top;
01020         write(top, "Config_info", gauge_xml);
01021         XMLReader from(top);
01022         XMLReader from2(from, "/Config_info");
01023         std::ostringstream os;
01024         from2.print(os);
01025         
01026         cfgInfo = os.str();
01027         
01028         if (cfgInfo != quarks[0]->getCfgInfo()){
01029           QDPIO::cerr << name << " : Quarks do not contain the same";
01030           QDPIO::cerr << " cfg info as the gauge field." ;
01031           QDPIO::cerr << "gauge: XX"<<cfgInfo<<"XX quarks: XX" ;
01032           QDPIO::cerr << quarks[0]->getCfgInfo()<<"XX"<<  endl;
01033           QDP_abort(1);
01034         }
01035       }      
01036 
01037       int decay_dir = quarks[0]->getDecayDir();
01038       //
01039       // Initialize the slow Fourier transform phases
01040       //
01041       SftMom phases(params.param.p2_max, false, decay_dir);
01042 
01043       // Create even/odd subsets on each timeslice:
01044       Set timerb;
01045       timerb.make(TimeSliceRBFunc(decay_dir));
01046       
01047       // Another sanity check. The seeds of all the quarks must be different
01048       // and thier decay directions must be the same 
01049       for(int n = 1 ; n < quarks.size(); n++){
01050         if(toBool(quarks[n]->getSeed()==quarks[0]->getSeed())){
01051           QDPIO::cerr << name << ": error, quark seeds are the same" << endl;
01052           QDP_abort(1);
01053         }
01054         
01055         if(toBool(quarks[n]->getDecayDir()!=quarks[0]->getDecayDir())){
01056           QDPIO::cerr<<name<< ": error, quark decay dirs do not match" <<endl;
01057           QDP_abort(1);
01058         }
01059       }
01060 
01061       // Instantiate the Dirac operator:
01062       Handle<EvenOddPrecLinearOperator<T,P,Q> > Doo=createOddOdd_Op(params.param,u);
01063 
01064       //Now read evecs from disk, if file is specified.
01065       multi1d<LatticeFermion> vec; // the vectors
01066       CholeskyFactors Clsk; // the Cholesky Factors 
01067       if (params.named_obj.evecs_file!="")
01068         ReadOPTEigCGVecs(vec,Clsk,params.named_obj.evecs_file);
01069       
01070       map< KeyOperator_t, ValOperator_t > data ;
01071       
01072       multi1d<multi1d< multi1d<LatticeFermion> > > quarkstilde(quarks.size());
01073       for(int n(0);n<quarks.size();n++){
01074         quarkstilde[n].resize(quarks[n]->getNumTimeSlices());
01075         for (int it(0) ; it < quarks[n]->getNumTimeSlices() ; it++){
01076           quarkstilde[n][it].resize(quarks[n]->getDilSize(it));
01077         }
01078       }
01079       
01080       /*** Everything is initialized, now to the real code ***/
01081       
01082       // chitilde = P_R S^-1 \eta_o
01083       // If there is no evecs file, then PR = 1
01084       if (params.named_obj.evecs_file!="")
01085         PRchi(quarkstilde, quarks, Doo, Clsk, vec, params.param, u);
01086       else
01087         PRchi(quarkstilde, quarks);
01088 
01089       for(int n(0);n<quarks.size();n++){
01090         for (int it(0) ; it < quarks[n]->getNumTimeSlices() ; it++){
01091           int t = quarks[n]->getT0(it) ;
01092           QDPIO::cout<<" Doing quark: "<< n <<endl ;
01093           QDPIO::cout<<"   quark: "<< n <<" has "<<quarks[n]->getDilSize(it);
01094           QDPIO::cout<<" dilutions on time slice "<< t <<endl ;
01095           for(int i = 0 ; i <  quarks[n]->getDilSize(it) ; i++){
01096             QDPIO::cout<<"   Doing dilution : "<<i<<endl ;
01097             multi1d<short int> d ;
01098             // Now, I want to do the two trace terms that have the chitilde. Thus
01099             // The q chosen should be from quarkstilde = PR*quarks->dilutedSolution()
01100             LatticeFermion qbar  = quarks[n]->dilutedSource(it,i);
01101             LatticeFermion q     = quarkstilde[n][it][i];
01102             QDPIO::cout<<"   Starting recursion "<<endl ;
01103             // this does both terms with the noise vectors
01104             // the 1 means to do sum over odd sites...
01105             do_disco(data, qbar, q, Doo, phases, t, timerb[2*t+1], d, params.param.max_path_length);
01106 
01107             QDPIO::cout<<" done with recursion! "
01108                        <<"  The length of the path is: "<<d.size()<<endl ;
01109           }
01110           QDPIO::cout<<" Done with dilutions for quark: "<<n <<endl ;
01111         }
01112       }
01113 
01114       // Okay, first we are going to normalize all the pieces above by the number of 
01115       // quarks...
01116       SerialDBKey <KeyOperator_t> key ;
01117       SerialDBData<ValOperator_t> val ;
01118       map< KeyOperator_t, ValOperator_t >::iterator it;
01119 
01120       for(it=data.begin();it!=data.end();it++){
01121         key.key()  = it->first  ;
01122         val.data().op.resize(it->second.op.size()) ;
01123         for(int i(0);i<it->second.op.size();i++){
01124           val.data().op[i] = it->second.op[i]/toDouble(quarks.size());
01125         }
01126       }
01127       
01128       // Now calculate the other pieces which need no normalization...
01129       // Note using just timeslices for quarks[0]...may be a problem
01130       // if quarks dilute on diff timeslices...
01131       
01132       for (int it(0) ; it < quarks[0]->getNumTimeSlices() ; it++){
01133         multi1d<short int> d ;
01134         int t = quarks[0]->getT0(it) ;
01135         // Now let's do the Tr[Dee^-1 gamma]
01136         do_disco(data,params.param, u, phases, t, timerb[2*t+0], d);
01137       }
01138       
01139       if (params.named_obj.evecs_file!=""){// Only if we have vectors...
01140         for (int it(0) ; it < quarks[0]->getNumTimeSlices() ; it++){
01141           multi1d<short int> d ;
01142           int t = quarks[0]->getT0(it) ;
01143           QDPIO::cout<<"   Starting recursion again"<<endl ;
01144           // Part with deflation..
01145           do_disco(data, Clsk, vec, params.param, Doo, u, t, timerb[2*t+1], phases,d);
01146           
01147           QDPIO::cout<<" done with recursion! "
01148                      <<"  The length of the path is: "<<d.size()<<endl ;
01149         }
01150       }
01151             
01152       //After all the pieces are computed we write the final result to the database
01153       // DB storage          
01154       BinaryStoreDB<SerialDBKey<KeyOperator_t>,SerialDBData<ValOperator_t> > qdp_db;
01155       
01156       // Open the file, and write the meta-data and the binary for this operator
01157       {
01158         XMLBufferWriter file_xml;
01159         
01160         push(file_xml, "DBMetaData");
01161         write(file_xml, "id", string("discoEigElemOp"));
01162         write(file_xml, "lattSize", QDP::Layout::lattSize());
01163         write(file_xml, "decay_dir", decay_dir);
01164         write(file_xml, "Params", params.param);
01165         write(file_xml, "Config_info", gauge_xml);
01166         pop(file_xml);
01167 
01168         std::string file_str(file_xml.str());
01169         qdp_db.setMaxUserInfoLen(file_str.size());
01170 
01171         qdp_db.open(params.named_obj.op_db_file, O_RDWR | O_CREAT, 0664);
01172 
01173         qdp_db.insertUserdata(file_str);
01174       }
01175 
01176       // Store all the data
01177       for(it=data.begin();it!=data.end();it++){
01178         key.key()  = it->first  ;
01179         val.data().op.resize(it->second.op.size()) ;
01180         // DON'T normalize to number of quarks here, because we only do it on a 
01181         // certain number of the terms in the trace...done above
01182         for(int i(0);i<it->second.op.size();i++)
01183           val.data().op[i] = it->second.op[i];
01184         qdp_db.insert(key,val) ;
01185       }
01186 
01187       // Close the namelist output file XMLDAT
01188       pop(xml_out);     // DiscoEigCG
01189       
01190       snoop.stop();
01191       QDPIO::cout << name << ": total time = "
01192                   << snoop.getTimeInSeconds() 
01193                   << " secs" << endl;
01194       
01195       QDPIO::cout << name << ": ran successfully" << endl;
01196       
01197       END_CODE();
01198     } 
01199   }  // namespace InlineDiscoEoEigCGEnv
01200 }// namespace chroma

Generated on Sun Nov 22 04:32:12 2009 for CHROMA by  doxygen 1.4.7