inline_stoch_group_meson_w.cc

Go to the documentation of this file.
00001 // $Id: inline_stoch_group_meson_w.cc,v 1.11 2008/06/20 15:17:37 edwards Exp $
00002 /*! \file
00003  * \brief Inline measurement of stochastic group meson operator
00004  *
00005  */
00006 
00007 #include "handle.h"
00008 #include "meas/inline/hadron/inline_stoch_group_meson_w.h"
00009 #include "meas/inline/abs_inline_measurement_factory.h"
00010 #include "meas/smear/quark_smearing_factory.h"
00011 #include "meas/smear/quark_smearing_aggregate.h"
00012 #include "meas/sources/source_smearing_aggregate.h"
00013 #include "meas/sources/source_smearing_factory.h"
00014 #include "meas/sinks/sink_smearing_aggregate.h"
00015 #include "meas/sinks/sink_smearing_factory.h"
00016 #include "meas/hadron/dilution_scheme_aggregate.h"
00017 #include "meas/hadron/dilution_scheme_factory.h"
00018 #include "meas/glue/mesplq.h"
00019 #include "meas/smear/displacement.h"
00020 #include "util/ferm/diractodr.h"
00021 #include "util/ft/sftmom.h"
00022 #include "util/info/proginfo.h"
00023 #include "meas/inline/make_xml_file.h"
00024 #include <sstream> 
00025 
00026 #include "meas/inline/io/named_objmap.h"
00027 
00028 namespace Chroma 
00029 { 
00030   /*!
00031    * \ingroup hadron
00032    *
00033    * @{
00034    */
00035   namespace InlineStochGroupMesonEnv 
00036   { 
00037     //! Number of quarks to be used in this construction
00038     const int N_quarks = 2;
00039         
00040         
00041     //
00042     // The spin basis matrix to goto Dirac
00043     //
00044     SpinMatrix rotate_mat(adj(DiracToDRMat()));
00045 
00046     // Reader for input parameters
00047     void read(XMLReader& xml, const string& path, InlineStochGroupMesonEnv::Params::Param_t& param)
00048     {
00049       XMLReader paramtop(xml, path);
00050 
00051       int version;
00052       read(paramtop, "version", version);
00053 
00054       switch (version) 
00055       {
00056       case 1:
00057         /**************************************************************************/
00058         break;
00059 
00060       default :
00061         /**************************************************************************/
00062 
00063         QDPIO::cerr << "Input parameter version " << version << " unsupported." << endl;
00064         QDP_abort(1);
00065       }
00066 
00067       read(paramtop, "creationOpContractType", param.creat_op_contract_type);
00068       read(paramtop, "annihilationOpContractType", param.annih_op_contract_type);
00069       read(paramtop, "mom2_max", param.mom2_max);
00070       read(paramtop, "displacement_length", param.displacement_length);
00071 
00072       param.quark_smearing = readXMLGroup(paramtop, "QuarkSmearing", "wvf_kind");
00073       param.link_smearing  = readXMLGroup(paramtop, "LinkSmearing", "LinkSmearingType");
00074       param.quark_dils     = readXMLArrayGroup(paramtop, "QuarkDilutions", "DilutionType");
00075     }
00076 
00077 
00078     // Writer for input parameters
00079     void write(XMLWriter& xml, const string& path, const InlineStochGroupMesonEnv::Params::Param_t& param)
00080     {
00081       push(xml, path);
00082 
00083       int version = 1;
00084 
00085       write(xml, "version", version);
00086       write(xml, "creationOpContractType", param.creat_op_contract_type);
00087       write(xml, "annihilationOpContractType", param.annih_op_contract_type);
00088       write(xml, "mom2_max", param.mom2_max);
00089       write(xml, "displacement_length", param.displacement_length);
00090       xml << param.quark_smearing.xml;
00091       xml << param.link_smearing.xml;
00092 
00093       push(xml, "QuarkDilutions");
00094 
00095       for(int i=0; i < param.quark_dils.size(); ++i)
00096         xml << param.quark_dils[i].xml;
00097 
00098       pop(xml);
00099 
00100       pop(xml);
00101     }
00102 
00103 
00104     //Reader for 2-quark operator file
00105     void read(XMLReader& xml, const string& path, InlineStochGroupMesonEnv::Params::NamedObject_t::TwoQuarkOpsFile_t& input)
00106     {
00107       XMLReader inputtop(xml, path);
00108 
00109       read(inputtop, "ops_file", input.ops_file);
00110       read(inputtop, "id", input.id);
00111     }
00112 
00113 
00114     // Writer for 2-quark operator file
00115     void write(XMLWriter& xml, const string& path, const InlineStochGroupMesonEnv::Params::NamedObject_t::TwoQuarkOpsFile_t& input)
00116     {
00117       push(xml, path);
00118       write(xml, "ops_file", input.ops_file);
00119       write(xml, "id", input.id);
00120       pop(xml);
00121     }
00122 
00123 
00124     //! Read named objects 
00125     void read(XMLReader& xml, const string& path, InlineStochGroupMesonEnv::Params::NamedObject_t& input)
00126     {
00127       XMLReader inputtop(xml, path);
00128 
00129       read(inputtop, "gauge_id", input.gauge_id);
00130       read(inputtop, "operators_file", input.operators_file);
00131       read(inputtop, "Quark_ids", input.quark_ids);
00132     }
00133 
00134     //! Write named objects
00135     void write(XMLWriter& xml, const string& path, const InlineStochGroupMesonEnv::Params::NamedObject_t& input)
00136     {
00137       push(xml, path);
00138 
00139       write(xml, "gauge_id", input.gauge_id);
00140       write(xml, "operators_file", input.operators_file);
00141       write(xml, "Quark_ids", input.quark_ids);
00142 
00143       pop(xml);
00144     }
00145   }
00146 
00147 
00148   namespace InlineStochGroupMesonEnv 
00149   { 
00150     // Anonymous namespace for registration
00151     namespace
00152     {
00153       AbsInlineMeasurement* createMeasurement(XMLReader& xml_in, 
00154                                               const std::string& path) 
00155       {
00156         return new InlineMeas(Params(xml_in, path));
00157       }
00158 
00159       //! Local registration flag
00160       bool registered = false;
00161     }
00162 
00163     const std::string name = "STOCH_GROUP_MESON";
00164 
00165     //! Register all the factories
00166     bool registerAll() 
00167     {
00168       bool success = true; 
00169       if (! registered)
00170       {
00171         success &= QuarkSourceSmearingEnv::registerAll();
00172         success &= QuarkSinkSmearingEnv::registerAll();
00173         success &= DilutionSchemeEnv::registerAll();
00174         success &= TheInlineMeasurementFactory::Instance().registerObject(name, createMeasurement);
00175         registered = true;
00176       }
00177       return success;
00178     }
00179 
00180 
00181     //! Anonymous namespace
00182     /*! Diagnostic stuff */
00183     namespace
00184     {
00185       StandardOutputStream& operator<<(StandardOutputStream& os, const multi1d<int>& d)
00186       {
00187         if (d.size() > 0)
00188         {
00189           os << d[0];
00190 
00191           for(int i=1; i < d.size(); ++i)
00192             os << " " << d[i];
00193         }
00194 
00195         return os;
00196       }
00197     }
00198 
00199 
00200     //----------------------------------------------------------------------------
00201     // Param stuff
00202     Params::Params()
00203     { 
00204       frequency = 0; 
00205       param.mom2_max = 0;
00206     }
00207 
00208     Params::Params(XMLReader& xml_in, const std::string& path) 
00209     {
00210       try 
00211       {
00212         XMLReader paramtop(xml_in, path);
00213 
00214         if (paramtop.count("Frequency") == 1)
00215           read(paramtop, "Frequency", frequency);
00216         else
00217           frequency = 1;
00218 
00219         // Read program parameters
00220         read(paramtop, "Param", param);
00221 
00222         // Read in the output propagator/source configuration info
00223         read(paramtop, "NamedObject", named_obj);
00224 
00225         // Possible alternate XML file pattern
00226         if (paramtop.count("xml_file") != 0) 
00227         {
00228           read(paramtop, "xml_file", xml_file);
00229         }
00230       }
00231       catch(const std::string& e) 
00232       {
00233         QDPIO::cerr << __func__ << ": Caught Exception reading XML: " << e << endl;
00234         QDP_abort(1);
00235       }
00236     }
00237 
00238 
00239     void
00240     Params::writeXML(XMLWriter& xml_out, const std::string& path) 
00241     {
00242       push(xml_out, path);
00243     
00244       // Parameters for source construction
00245       write(xml_out, "Param", param);
00246 
00247       // Write out the output propagator/source configuration info
00248       write(xml_out, "NamedObject", named_obj);
00249 
00250       pop(xml_out);
00251     }
00252 
00253 
00254 
00255     //--------------------------------------------------------------
00256     //! 2-quark operator structure
00257     struct TwoQuarkOps_t
00258     {
00259       struct TwoQuarkOp_t
00260       {
00261         struct QuarkInfo_t
00262         {
00263           multi1d<int>  displacement;   /*!< Orig plus/minus 1-based directional displacements */
00264           int           spin;           /*!< 1-based spin index */
00265         };
00266 
00267         multi1d<QuarkInfo_t>  quark;    /*!< Displacement and spin for each quark */
00268         std::string name;               /*!< Name of the 2-quark operator */
00269       };
00270         
00271       multi1d<TwoQuarkOp_t> ops; /*!< 2-quark ops within a file */
00272     };
00273 
00274     //! Write quark 
00275     void write(XMLWriter& xml, const string& path, 
00276                const TwoQuarkOps_t::TwoQuarkOp_t::QuarkInfo_t& input)
00277     {
00278       push(xml, path);
00279 
00280       write(xml, "Displacement", input.displacement);
00281       write(xml, "Spin", input.spin);
00282 
00283       pop(xml);
00284     }
00285 
00286     //! Write two quark op 
00287     void write(XMLWriter& xml, const string& path, 
00288                const TwoQuarkOps_t::TwoQuarkOp_t& input)
00289     {
00290       push(xml, path);
00291 
00292       write(xml, "Quarks", input.quark);
00293       write(xml, "Name", input.name);
00294 
00295       pop(xml);
00296     }
00297         
00298 
00299 
00300     //---------------------------------------------------------------------------
00301 
00302 
00303     //! The key for smeared quarks 
00304     struct KeySmearedQuark_t
00305     {
00306       int  t0;              /*!< Time of source */
00307       int dil;              /*!< dilution component per timeslice */
00308     };
00309 
00310 
00311     //! Support for the keys of smeared quarks 
00312     bool operator<(const KeySmearedQuark_t& a, const KeySmearedQuark_t& b)
00313     {
00314       multi1d<int> lga(2);
00315       lga[0] = a.t0;
00316       lga[1] = a.dil;
00317 
00318       multi1d<int> lgb(2);
00319       lgb[0] = b.t0;
00320       lgb[1] = b.dil;
00321 
00322       return (lga < lgb);
00323     }
00324 
00325 
00326     struct SmearedQuark_t
00327     {
00328       LatticeFermion quark;
00329     };
00330 
00331     //----------------------------------------------------------------------------
00332     //! The key for smeared and displaced color vectors
00333     struct KeySmearedDispColorVector_t
00334     {
00335       int  t0;              /*!< Time of source */
00336       int  dil;             /*!< dilution component per timeslice */
00337 
00338       multi1d<int>  displacement;    /*!< Orig plus/minus 1-based directional displacements */
00339       int           spin;            /*!< 1-based spin index */
00340     };
00341 
00342 
00343     //! Support for the keys of smeared and displaced color vectors
00344     bool operator<(const KeySmearedDispColorVector_t& a, const KeySmearedDispColorVector_t& b)
00345     {
00346       multi1d<int> lgaa(3);
00347       lgaa[0] = a.spin;
00348       lgaa[1] = a.t0;
00349       lgaa[2] = a.dil;
00350       multi1d<int> lga = concat(lgaa, a.displacement);
00351 
00352       multi1d<int> lgbb(3);
00353       lgbb[0] = b.spin;
00354       lgbb[1] = b.t0;
00355       lgbb[2] = b.dil;
00356       multi1d<int> lgb = concat(lgbb, b.displacement);
00357 
00358       return (lga < lgb);
00359     }
00360 
00361 
00362     //! The value of the map
00363     struct SmearedDispColorVector_t
00364     {
00365       multi1d<LatticeComplex> vec;
00366     };
00367 
00368 
00369     //----------------------------------------------------------------------------
00370     //! The smeared and displaced objects
00371     class SmearedDispObjects
00372     {
00373     public:
00374       //! Constructor from smeared map 
00375       SmearedDispObjects(int disp_length,
00376                          multi1d< Handle< DilutionScheme<LatticeFermion> > > dil_quarks,        
00377                          Handle< QuarkSmearing<LatticeFermion> > qsmr,
00378                          const multi1d<LatticeColorMatrix> & u_smr);
00379 
00380       //! Destructor
00381       ~SmearedDispObjects() {}
00382 
00383       //! Accessor
00384       virtual multi1d<LatticeComplex> getDispSource(int quark_num, 
00385                                                     const KeySmearedDispColorVector_t& key);
00386 
00387       //! Accessor
00388       virtual multi1d<LatticeComplex> getDispSolution(int quark_num,
00389                                                       const KeySmearedDispColorVector_t& key);
00390 
00391     protected:
00392       //! Displace an object
00393       virtual const multi1d<LatticeComplex>&  displaceObject(
00394         map<KeySmearedDispColorVector_t, SmearedDispColorVector_t>& disp_quark_map,
00395         const KeySmearedDispColorVector_t& key,
00396         const LatticeFermion& smrd_q);
00397                         
00398       //! Smear sources and solutions
00399       virtual const LatticeFermion&
00400       smearSource(int qnum , const KeySmearedQuark_t & key);
00401                                          
00402       virtual const LatticeFermion&
00403       smearSolution(int qnum , const KeySmearedQuark_t & key);
00404 
00405     private:
00406       multi1d< Handle< DilutionScheme<LatticeFermion> > > diluted_quarks;       
00407       Handle < QuarkSmearing<LatticeFermion> > quarkSmearing;
00408                 
00409       //!Gauge field 
00410       const multi1d<LatticeColorMatrix> & u;
00411                         
00412       //! Displacement length
00413       int displacement_length;
00414 
00415                         
00416       //! Maps of smeared color vectors 
00417       multi1d< map<KeySmearedQuark_t, SmearedQuark_t> > smeared_src_maps;
00418       multi1d< map<KeySmearedQuark_t, SmearedQuark_t> > smeared_soln_maps;
00419 
00420       
00421       //!Maps of smeared displaced color vectors 
00422       multi1d< map<KeySmearedDispColorVector_t, SmearedDispColorVector_t> > disp_src_maps;
00423       multi1d< map<KeySmearedDispColorVector_t, SmearedDispColorVector_t> > disp_soln_maps;
00424     };
00425 
00426         
00427     // Constructor from smeared map 
00428     SmearedDispObjects::SmearedDispObjects(int disp_length,
00429                                            multi1d< Handle< DilutionScheme<LatticeFermion> > > dil_quarks,
00430                                            Handle< QuarkSmearing<LatticeFermion> > qsmr,
00431                                            const multi1d<LatticeColorMatrix> & u_smr) :
00432       displacement_length(disp_length),diluted_quarks(dil_quarks),
00433       quarkSmearing(qsmr), u(u_smr)
00434     {
00435       if (diluted_quarks.size() != N_quarks)
00436       {
00437         QDPIO::cerr << __func__ << ": expected num_quarks=" << N_quarks << endl;
00438         QDP_abort(1);
00439       }
00440 
00441       smeared_src_maps.resize(N_quarks);
00442       smeared_soln_maps.resize(N_quarks);
00443                         
00444       disp_src_maps.resize(N_quarks);
00445       disp_soln_maps.resize(N_quarks);
00446     }
00447 
00448 
00449     const LatticeFermion&
00450     SmearedDispObjects::smearSource(int qnum, 
00451                                     const KeySmearedQuark_t & key)
00452     {
00453       map<KeySmearedQuark_t, SmearedQuark_t> & qmap = smeared_src_maps[qnum];
00454 
00455       //If entry is not in map create it
00456       if ( qmap.find(key) == qmap.end() )
00457       {
00458         // Insert an empty entry and then modify it. This saves on
00459         // copying the data around
00460         {
00461           SmearedQuark_t smrd_empty;
00462           qmap.insert(std::make_pair(key, smrd_empty));
00463 
00464           // Sanity check - the entry better be there
00465           if ( qmap.find(key) == qmap.end() )
00466           {
00467             QDPIO::cerr << __func__ 
00468                         << ": internal error - could not insert empty key in map"
00469                         << endl;
00470             QDP_abort(1);
00471           }                   
00472         }
00473 
00474         // Modify the previous empty entry
00475         SmearedQuark_t& smrd_q = qmap.find(key)->second;
00476              
00477         StopWatch snoop;
00478 
00479         snoop.reset();
00480         snoop.start();
00481         
00482         LatticeFermion f = diluted_quarks[qnum]->dilutedSource(key.t0, key.dil);
00483 
00484         (*quarkSmearing)(f, u);
00485 
00486         // The first set of quarks will get a gamma_5 to implement the oper we need
00487         // op=  eta_1^dag * [whatever gamma and U oper structure] * gamma_5 eta_0^dag
00488         SpinMatrix mat;
00489         if (qnum == 0)
00490         {
00491           mat = rotate_mat * Gamma(15);
00492         }
00493         else
00494         {
00495           mat = rotate_mat;
00496         }
00497                                 
00498         smrd_q.quark = mat * f;
00499 
00500         snoop.stop();
00501 
00502         QDPIO::cout << " Smeared Sources: Quark = "<< qnum <<" t0 = "
00503                     << key.t0 <<" dil = "<< key.dil << " Time = "<< snoop.getTimeInSeconds() <<" sec"<<endl;
00504 
00505         // Insert
00506         qmap.insert(std::make_pair(key, smrd_q));
00507       
00508       } // if find in map
00509 
00510       // The key now must exist in the map, so return the smeared quark field
00511 
00512       return (qmap.find(key)->second).quark ;
00513     }
00514 
00515         
00516                 
00517     const LatticeFermion&
00518     SmearedDispObjects::smearSolution(int qnum , 
00519                                       const KeySmearedQuark_t & key)
00520     {
00521       map<KeySmearedQuark_t, SmearedQuark_t> & qmap = smeared_soln_maps[qnum];
00522 
00523       //If entry is not in map create it
00524       if ( qmap.find(key) == qmap.end() )
00525       {
00526 
00527         // Insert an empty entry and then modify it. This saves on
00528         // copying the data around
00529         {
00530           SmearedQuark_t smrd_empty;
00531           qmap.insert(std::make_pair(key, smrd_empty));
00532 
00533           // Sanity check - the entry better be there
00534           if ( qmap.find(key) == qmap.end() )
00535           {
00536             QDPIO::cerr << __func__ 
00537                         << ": internal error - could not insert empty key in map"
00538                         << endl;
00539             QDP_abort(1);
00540           }                   
00541         }
00542 
00543         // Modify the previous empty entry
00544         SmearedQuark_t& smrd_q = qmap.find(key)->second;
00545              
00546         StopWatch snoop;
00547         snoop.reset();
00548         snoop.start();
00549         
00550         LatticeFermion f = diluted_quarks[qnum]->dilutedSolution(key.t0, key.dil);
00551 
00552         (*quarkSmearing)(smrd_q.quark, u);
00553 
00554         // The first set of quarks will get a gamma_5 to implement the oper. we need
00555         // op=  psi_0^dag * gamma_5 * [whatever gamma and U oper structure] * psi_1^dag
00556         SpinMatrix mat;
00557         if (qnum == 0)
00558         {
00559           mat = rotate_mat * Gamma(15);
00560         }
00561         else
00562         {
00563           mat = rotate_mat;
00564         }
00565                                 
00566         smrd_q.quark = mat * f;
00567               
00568         snoop.stop();
00569 
00570         QDPIO::cout << " Smeared Sinks: Quark = "<< qnum <<" t0 = "
00571                     << key.t0 <<" dil = "<< key.dil << " Time = "<< snoop.getTimeInSeconds() <<" sec"<<endl;
00572         
00573         // Insert
00574         qmap.insert(std::make_pair(key, smrd_q));
00575       
00576       } // if find in map
00577 
00578       // The key now must exist in the map, so return the smeared quark field
00579 
00580       return (qmap.find(key)->second).quark ;
00581     }
00582 
00583     //! Accessor
00584     multi1d<LatticeComplex>
00585     SmearedDispObjects::getDispSource(int quark_num, 
00586                                       const KeySmearedDispColorVector_t& key)
00587     {
00588       //Get Smeared quark 
00589       KeySmearedQuark_t smr_key;
00590       smr_key.t0 = key.t0;
00591       smr_key.dil = key.dil;
00592 
00593       const LatticeFermion& smrd_q = smearSource(quark_num, smr_key);
00594                                         
00595       multi1d<LatticeComplex> vec;
00596 
00597       //Check if any displacement is needed
00598       if (displacement_length == 0) 
00599       {
00600         vec.resize(Nc);
00601         LatticeColorVector colvec = peekSpin( smrd_q, key.spin - 1);
00602 
00603         for (int c = 0 ; c < Nc ; ++c)
00604           vec[c] = peekColor( colvec, c);
00605 
00606       }
00607       else
00608       {
00609         vec = displaceObject( disp_src_maps[quark_num] , key , smrd_q);
00610       }
00611 
00612       return vec;
00613     }
00614 
00615     //! Accessor
00616     multi1d<LatticeComplex>
00617     SmearedDispObjects::getDispSolution(int quark_num, 
00618                                         const KeySmearedDispColorVector_t& key)
00619     {
00620       //Get Smeared quark 
00621       KeySmearedQuark_t smr_key;
00622       smr_key.t0 = key.t0;
00623       smr_key.dil = key.dil;
00624 
00625       const LatticeFermion& smrd_q = smearSolution(quark_num, smr_key);
00626                                 
00627       multi1d<LatticeComplex> vec;
00628 
00629       //Check if any displacement is needed
00630       if (displacement_length == 0) 
00631       {
00632         vec.resize(Nc);
00633         LatticeColorVector colvec = peekSpin( smrd_q, key.spin - 1);
00634 
00635         for (int c = 0 ; c < Nc ; ++c)
00636           vec[c] = peekColor( colvec, c);
00637 
00638       }
00639       else
00640       {
00641         vec = displaceObject( disp_soln_maps[quark_num] , key , smrd_q);
00642       }
00643 
00644       return vec;
00645     }
00646 
00647 
00648     //! Accessor
00649     const multi1d<LatticeComplex> &
00650     SmearedDispObjects::displaceObject(
00651       map<KeySmearedDispColorVector_t, SmearedDispColorVector_t>& disp_quark_map,
00652       const KeySmearedDispColorVector_t& key,
00653       const LatticeFermion& smrd_q)
00654     {
00655       StopWatch snoop;
00656 
00657       // If no entry, then create a displaced version of the quark
00658       if (disp_quark_map.find(key) == disp_quark_map.end())
00659       {
00660         //            cout << __func__ 
00661         //                 << ": n=" << n
00662         //                 << " l=" << l
00663         //                 << " i=" << i 
00664         //                 << " disp=" << term.quark[i].displacement
00665         //                 << " len=" << term.quark[i].disp_len
00666         //                 << " dir=" << term.quark[i].disp_dir
00667         //                 << endl;
00668 
00669         // Insert an empty entry and then modify it. This saves on
00670         // copying the data around
00671         {
00672           SmearedDispColorVector_t disp_empty;
00673 
00674           snoop.reset();
00675           snoop.start();
00676 
00677           disp_quark_map.insert(std::make_pair(key, disp_empty));
00678 
00679           snoop.stop();
00680 
00681           QDPIO::cout<<"Inserted key in map: time = "<< snoop.getTimeInSeconds() << "secs"<<endl;
00682 
00683           // Sanity check - the entry better be there
00684           if (disp_quark_map.find(key) == disp_quark_map.end())
00685           {
00686             QDPIO::cerr << __func__ 
00687                         << ": internal error - could not insert empty key in map"
00688                         << endl;
00689             QDP_abort(1);
00690           }                   
00691         }
00692 
00693         // Modify the previous empty entry
00694         SmearedDispColorVector_t& disp_q = disp_quark_map.find(key)->second;
00695 
00696         snoop.reset();
00697         snoop.start();
00698 
00699         //Chroma uses a zero-based spin convention
00700         LatticeColorVector vec = peekSpin(smrd_q,  key.spin - 1);
00701 
00702         for(int i=0; i < key.displacement.size(); ++i)
00703         {
00704           if (key.displacement[i] > 0)
00705           {
00706             int disp_dir = key.displacement[i] - 1;
00707             int disp_len = displacement_length;
00708             displacement(u, vec, disp_len, disp_dir);
00709           }
00710           else if (key.displacement[i] < 0)
00711           {
00712             int disp_dir = -key.displacement[i] - 1;
00713             int disp_len = -displacement_length;
00714             displacement(u, vec, disp_len, disp_dir);
00715           }
00716         }
00717 
00718         snoop.stop();
00719 
00720         QDPIO::cout << "Displaced Quarks: Spin = "<<key.spin<<" Disp = "
00721                     << key.displacement <<" Time = "<<snoop.getTimeInSeconds() <<" sec"<<endl;
00722 
00723         disp_q.vec.resize(Nc);
00724 
00725         for(int i = 0 ; i < Nc ; ++i ) 
00726         {
00727           disp_q.vec[i] = peekColor(vec, i);
00728         }
00729 
00730       } // if find in map
00731 
00732       snoop.reset();
00733       snoop.start();
00734 
00735       // The key now must exist in the map, so return the vector
00736       SmearedDispColorVector_t& disp_q = disp_quark_map.find(key)->second;
00737 
00738       snoop.stop(); 
00739 
00740       QDPIO::cout << "Retrieved entry from map : time = "<< snoop.getTimeInSeconds() << "secs "<<endl;
00741 
00742       return disp_q.vec;
00743     }
00744 
00745 
00746     //----------------------------------------------------------------------------
00747     // Color contract two fermions
00748     void makeColorSinglet (LatticeComplex& singlet, 
00749                            const multi1d<LatticeComplex>& q0,
00750                            const multi1d<LatticeComplex>& q1, 
00751                            const Subset& subset)
00752     {
00753       singlet[subset]  = q0[0] * q1[0];
00754       for(int i=1; i < q0.size(); ++i)
00755         singlet[subset] += q0[i] * q1[i];
00756     }
00757 
00758 
00759     //----------------------------------------------------------------------------
00760     // Color contract two fermions
00761     multi2d<DComplex> contractOp (SmearedDispObjects& smrd_disp_vecs,
00762                                   int n0, const KeySmearedDispColorVector_t& k0,
00763                                   int n1, const KeySmearedDispColorVector_t& k1,
00764                                   MesonOpType contractType, 
00765                                   const SftMom& phases,
00766                                   int t0)
00767     {
00768       multi2d<DComplex> op_sum;
00769       LatticeComplex singlet;
00770 
00771       switch(contractType)
00772       {
00773       case MESON_OP_TYPE_SOURCE_SOURCE:
00774         makeColorSinglet(singlet,
00775                          smrd_disp_vecs.getDispSource(n0, k0),
00776                          smrd_disp_vecs.getDispSource(n1, k1),
00777                          phases.getSet()[t0]);
00778         op_sum = phases.sft(singlet, t0);
00779         break;
00780 
00781       case MESON_OP_TYPE_SOURCE_SOLUTION:
00782         makeColorSinglet(singlet,
00783                          smrd_disp_vecs.getDispSource(n0, k0),
00784                          smrd_disp_vecs.getDispSolution(n1, k1),
00785                          phases.getSet()[t0]);
00786         op_sum = phases.sft(singlet, t0);
00787         break;
00788 
00789       case MESON_OP_TYPE_SOLUTION_SOURCE:
00790         makeColorSinglet(singlet,
00791                          smrd_disp_vecs.getDispSolution(n0, k0),
00792                          smrd_disp_vecs.getDispSource(n1, k1),
00793                          phases.getSet()[t0]);
00794         op_sum = phases.sft(singlet, t0);
00795         break;
00796 
00797       case MESON_OP_TYPE_SOLUTION_SOLUTION:
00798         makeColorSinglet(singlet,
00799                          smrd_disp_vecs.getDispSolution(n0, k0),
00800                          smrd_disp_vecs.getDispSolution(n1, k1),
00801                          all);
00802         op_sum = phases.sft(singlet);
00803         break;
00804       }
00805 
00806       return op_sum;
00807     }
00808                   
00809 
00810     //----------------------------------------------------------------------------
00811     //! Meson operator
00812     struct MesonOperator_t
00813     {
00814       //! Meson operator time slices corresponding to location of operator source
00815       struct TimeSlices_t
00816       {
00817         //! Meson operator dilutions
00818         struct Dilutions_t
00819         {
00820           //! Momentum projected correlator
00821           struct Mom_t
00822           {
00823             multi1d<int>       mom;         /*!< D-1 momentum of this operator */
00824             multi1d<DComplex>  op;          /*!< Momentum projected operator */
00825           };
00826 
00827           multi1d<Mom_t> mom_projs;         /*!< Holds momentum projections of the operator */
00828         };
00829 
00830         multi2d<Dilutions_t> dilutions;     /*!< Hybrid list indices */
00831         int t0;                               /*!< Actual time corresponding to this timeslice */
00832       };
00833 
00834       GroupXML_t    smearing;          /*!< String holding quark smearing xml */
00835 
00836       Seed          seed_l;            /*!< Id of left quark */
00837       Seed          seed_r;            /*!< Id of right quark */
00838 
00839       GroupXML_t    dilution_l;        /*!< Dilution scheme of left quark */ 
00840       GroupXML_t    dilution_r;        /*!< Dilution scheme of right quark */ 
00841 
00842       std::string   id;                /*!< Tag/ID used in analysis codes */
00843 
00844       MesonOpType   op_contract_type;  /*<! Contraction type for creation op */
00845       int           mom2_max;          /*!< |\vec{p}|^2 */
00846       int           decay_dir;         /*!< Direction of decay */
00847 
00848       multi1d<TimeSlices_t> time_slices; /*!< Time slices of the lattice that are used */
00849     };
00850 
00851 
00852     //----------------------------------------------------------------------------
00853     //! MesonOperator header writer
00854     void write(XMLWriter& xml, const string& path, const MesonOperator_t& param)
00855     {
00856       push(xml, path);
00857 
00858       int version = 1;
00859       write(xml, "version", version);
00860       write(xml, "id", param.id);
00861       write(xml, "opContractType", param.op_contract_type);
00862       write(xml, "mom2_max", param.mom2_max);
00863       write(xml, "decay_dir", param.decay_dir);
00864       write(xml, "seed_l", param.seed_l);
00865       write(xml, "seed_r", param.seed_r);
00866 
00867       push(xml, "dilution_l");
00868       xml << param.dilution_l.xml; 
00869       pop(xml);
00870 
00871       push(xml, "dilution_r");
00872       xml << param.dilution_r.xml; 
00873       pop(xml);
00874                         
00875       xml <<  param.smearing.xml;
00876         
00877       pop(xml);
00878     }
00879 
00880 
00881 
00882     //! MesonOperator binary writer
00883     void write(BinaryWriter& bin, const MesonOperator_t::TimeSlices_t::Dilutions_t::Mom_t& param)
00884     {
00885       write(bin, param.mom);
00886       write(bin, param.op);
00887     }
00888 
00889     //! MesonOperator binary writer
00890     void write(BinaryWriter& bin, const MesonOperator_t::TimeSlices_t::Dilutions_t& param)
00891     {
00892       write(bin, param.mom_projs);
00893     }
00894 
00895     //! MesonOperator binary writer
00896     void write(BinaryWriter& bin, const MesonOperator_t::TimeSlices_t& param)
00897     {
00898       write(bin, param.dilutions);
00899       write(bin, param.t0);
00900     }
00901 
00902     //! MesonOperator binary writer
00903     void write(BinaryWriter& bin, const MesonOperator_t& param)
00904     {
00905       write(bin, param.seed_l);
00906       write(bin, param.seed_r);
00907       write(bin, param.mom2_max);
00908       write(bin, param.decay_dir);
00909       write(bin, param.time_slices);
00910     }
00911 
00912 
00913     //! Read 2-quark operators file, assign correct displacement length
00914     void readOps(TwoQuarkOps_t& oplist, 
00915                  const std::string& ops_file)
00916     {
00917       START_CODE();
00918 
00919       TextFileReader reader(ops_file);
00920 
00921       int num_ops;
00922       reader >> num_ops;
00923       oplist.ops.resize(num_ops);
00924 
00925       //Loop over ops within a file
00926       for(int n=0; n < oplist.ops.size(); ++n)
00927       {
00928         std::string name; 
00929         reader >> name;
00930         oplist.ops[n].name = name;  
00931 
00932         TwoQuarkOps_t::TwoQuarkOp_t& qqq = oplist.ops[n];
00933         qqq.quark.resize(N_quarks);
00934 
00935         // Read 1-based spin
00936         reader >> qqq.quark[0].spin >> qqq.quark[1].spin;
00937 
00938         // Read 1-based displacement only for the right quark
00939         qqq.quark[0].displacement.resize(1);
00940         qqq.quark[0].displacement[0] = 0;
00941 
00942         int ndisp;
00943         reader >> ndisp;
00944         multi1d<int> displacement(ndisp);
00945         for(int i=0; i < ndisp; ++i)
00946           reader >> displacement[i];
00947 
00948         qqq.quark[1].displacement = displacement;
00949       } //n
00950 
00951       reader.close();
00952 
00953       END_CODE();
00954     } //void readOps
00955 
00956 
00957     //-------------------------------------------------------------------------------
00958     // Function call
00959     void 
00960     InlineMeas::operator()(unsigned long update_no,
00961                            XMLWriter& xml_out) 
00962     {
00963       // If xml file not empty, then use alternate
00964       if (params.xml_file != "")
00965       {
00966         string xml_file = makeXMLFileName(params.xml_file, update_no);
00967 
00968         push(xml_out, "stoch_meson");
00969         write(xml_out, "update_no", update_no);
00970         write(xml_out, "xml_file", xml_file);
00971         pop(xml_out);
00972 
00973         XMLFileWriter xml(xml_file);
00974         func(update_no, xml);
00975       }
00976       else
00977       {
00978         func(update_no, xml_out);
00979       }
00980     }
00981 
00982 
00983     // Function call
00984     void 
00985     InlineMeas::func(unsigned long update_no,
00986                      XMLWriter& xml_out) 
00987     {
00988       START_CODE();
00989 
00990       StopWatch snoop;
00991       snoop.reset();
00992       snoop.start();
00993 
00994       
00995       StopWatch swiss;
00996                         
00997       // Test and grab a reference to the gauge field
00998       XMLBufferWriter gauge_xml;
00999       try
01000       {
01001         TheNamedObjMap::Instance().getData< multi1d<LatticeColorMatrix> >(params.named_obj.gauge_id);
01002         TheNamedObjMap::Instance().get(params.named_obj.gauge_id).getRecordXML(gauge_xml);
01003       }
01004       catch( std::bad_cast ) 
01005       {
01006         QDPIO::cerr << InlineStochGroupMesonEnv::name << ": caught dynamic cast error" 
01007                     << endl;
01008         QDP_abort(1);
01009       }
01010       catch (const string& e) 
01011       {
01012         QDPIO::cerr << InlineStochGroupMesonEnv::name << ": map call failed: " << e 
01013                     << endl;
01014         QDP_abort(1);
01015       }
01016       const multi1d<LatticeColorMatrix>& u = 
01017         TheNamedObjMap::Instance().getData< multi1d<LatticeColorMatrix> >(params.named_obj.gauge_id);
01018 
01019       push(xml_out, "StochGroupMeson");
01020       write(xml_out, "update_no", update_no);
01021 
01022       QDPIO::cout << InlineStochGroupMesonEnv::name << ": Stochastic Meson Operator" << endl;
01023 
01024       proginfo(xml_out);    // Print out basic program info
01025 
01026       // Write out the input
01027       params.writeXML(xml_out, "Input");
01028 
01029       // Write out the config info
01030       write(xml_out, "Config_info", gauge_xml);
01031 
01032       push(xml_out, "Output_version");
01033       write(xml_out, "out_version", 1);
01034       pop(xml_out);
01035 
01036       //First calculate some gauge invariant observables just for info.
01037       //This is really cheap.
01038       MesPlq(xml_out, "Observables", u);
01039 
01040       // Save current seed
01041       Seed ran_seed;
01042       QDP::RNG::savern(ran_seed);
01043 
01044       //
01045       // Construct the dilution scheme for each of the 2 quarks
01046       // 
01047       if (params.param.quark_dils.size() != N_quarks)
01048       {
01049         QDPIO::cerr << name << ": expecting 2 quark dilutions" << endl;
01050         QDP_abort(1);
01051       }
01052 
01053       multi1d< Handle< DilutionScheme<LatticeFermion> > > diluted_quarks(N_quarks);  /*!< Here is the big (dil) pickle */
01054 
01055       try
01056       {
01057         // Loop over the 2 quark dilutions
01058         for(int n = 0; n < params.param.quark_dils.size(); ++n)
01059         {
01060           const GroupXML_t& dil_xml = params.param.quark_dils[n];
01061 
01062           std::istringstream  xml_d(dil_xml.xml);
01063           XMLReader  diltop(xml_d);
01064           QDPIO::cout << "Dilution type = " << dil_xml.id << endl;
01065         
01066           diluted_quarks[n] = TheFermDilutionSchemeFactory::Instance().createObject(
01067             dil_xml.id, diltop, dil_xml.path);
01068         }
01069       }
01070       catch(const std::string& e) 
01071       {
01072         QDPIO::cerr << name << ": Caught Exception constructing dilution scheme: " << e << endl;
01073         QDP_abort(1);
01074       }
01075 //------------------------------------------------------------------------
01076 //Sanity checks 
01077 
01078       //The participating timeslices must match for each quark
01079       //grab info from first quark to prime the work
01080 
01081       multi1d<int> participating_timeslices( diluted_quarks[0]->getNumTimeSlices() );
01082 
01083       for (int t0 = 0 ; t0 < participating_timeslices.size() ; ++t0)
01084       {
01085         participating_timeslices[t0] = diluted_quarks[0]->getT0(t0);
01086       }
01087 
01088       for (int n = 1 ; n < N_quarks ; ++n)
01089       {
01090         if ( diluted_quarks[n]->getNumTimeSlices() != participating_timeslices.size() )
01091         {
01092           QDPIO::cerr << name << " : Quarks do not contain the same number of dilution timeslices: Quark " 
01093                       << n << endl; 
01094 
01095           QDP_abort(1);
01096         }
01097 
01098         for (int t0 = 0 ; t0 < participating_timeslices.size() ; ++t0)
01099         {
01100           if  ( diluted_quarks[n]->getT0(t0) != participating_timeslices[t0] )
01101           {
01102             QDPIO::cerr << name << " : Quarks do not contain the same participating timeslices: Quark "<<
01103               n << " timeslice "<< t0 << endl;
01104 
01105             QDP_abort(1);
01106           }
01107         }
01108       }
01109                 
01110       //Another Sanity check, the two quarks must all be 
01111       //inverted on the same cfg
01112       for (int n = 1 ; n < N_quarks ; ++n)
01113       {
01114         if (diluted_quarks[0]->getCfgInfo() != diluted_quarks[n]->getCfgInfo())
01115         {
01116           QDPIO::cerr << name 
01117                       << " : Quarks do not contain the same cfg info, quark "<< n << endl;
01118         
01119           QDP_abort(1);
01120         }
01121                         
01122       }
01123 
01124       //Also ensure that the cfg on which the inversions were performed 
01125       //is the same as the cfg that we are using
01126       { 
01127         std::string cfgInfo; 
01128 
01129         //Really ugly way of doing this(Robert Heeeelp!!)
01130         XMLBufferWriter top;
01131         write(top, "Config_info", gauge_xml);
01132         XMLReader from(top);
01133         XMLReader from2(from, "/Config_info");
01134         std::ostringstream os;
01135         from2.print(os);
01136 
01137         cfgInfo = os.str();
01138 
01139         if (cfgInfo != diluted_quarks[0]->getCfgInfo())
01140         {
01141           QDPIO::cerr << name 
01142                       << " : Quarks do not contain the same cfg info as the gauge field."
01143                       << "gauge: XX"<<cfgInfo<<"XX quarks: XX"<<diluted_quarks[0]->getCfgInfo()<<"XX"<<  endl;
01144 
01145 
01146           QDP_abort(1);
01147         }
01148       }
01149 
01150       //
01151       // Initialize the slow Fourier transform phases
01152       //
01153       int decay_dir = diluted_quarks[0]->getDecayDir();
01154 
01155       SftMom phases(params.param.mom2_max, false, decay_dir);
01156 
01157       // Sanity check - if this doesn't work we have serious problems
01158       if (phases.numSubsets() != QDP::Layout::lattSize()[decay_dir])
01159       {
01160         QDPIO::cerr << name << ": number of time slices not equal to that in the decay direction: " 
01161                     << QDP::Layout::lattSize()[decay_dir]
01162                     << endl;
01163         QDP_abort(1);
01164       }
01165 
01166                 
01167       // Another sanity check. The seeds of all the quarks must be different
01168       // and thier decay directions must be the same 
01169       for(int n = 1 ; n < diluted_quarks.size(); ++n)
01170       {
01171         if ( toBool( diluted_quarks[n]->getSeed() == diluted_quarks[0]->getSeed() ) ) 
01172         {
01173           QDPIO::cerr << name << ": error, quark seeds are the same" << endl;
01174           QDP_abort(1);
01175         }
01176 
01177         if ( toBool( diluted_quarks[n]->getDecayDir() != diluted_quarks[0]->getDecayDir() ) )
01178         {
01179           QDPIO::cerr << name << ": error, quark decay dirs do not match" <<endl;
01180           QDP_abort(1);
01181         }
01182 
01183       }
01184 
01185       //
01186       // Smear the gauge field if needed
01187       //
01188       multi1d<LatticeColorMatrix> u_smr = u;
01189 
01190       try
01191       {
01192         std::istringstream  xml_l(params.param.link_smearing.xml);
01193         XMLReader  linktop(xml_l);
01194         QDPIO::cout << "Link smearing type = " << params.param.link_smearing.id << endl;
01195         
01196         
01197         Handle< LinkSmearing >
01198           linkSmearing(TheLinkSmearingFactory::Instance().createObject(params.param.link_smearing.id,
01199                                                                        linktop, params.param.link_smearing.path));
01200 
01201         (*linkSmearing)(u_smr);
01202       }
01203       catch(const std::string& e) 
01204       {
01205         QDPIO::cerr << name << ": Caught Exception link smearing: " << e << endl;
01206         QDP_abort(1);
01207       }
01208 
01209       MesPlq(xml_out, "Smeared_Observables", u_smr);
01210 
01211       //
01212       // Read operator coefficients
01213       //
01214       QDPIO::cout << "Reading 2-quark operators" << endl;
01215       TwoQuarkOps_t qqq_oplist; 
01216 
01217       readOps(qqq_oplist, params.named_obj.operators_file.ops_file);
01218 
01219       //
01220       // Create the quark smearing factory 
01221       //
01222       Handle< QuarkSmearing<LatticeFermion> > quarkSmearing;
01223 
01224       try
01225       {
01226         QDPIO::cout << "Create quark smearing object" << endl;
01227 
01228         // Create the quark smearing object
01229         std::istringstream  xml_s(params.param.quark_smearing.xml);
01230         XMLReader  smeartop(xml_s);
01231         
01232         quarkSmearing =
01233           TheFermSmearingFactory::Instance().createObject(params.param.quark_smearing.id,
01234                                                           smeartop, params.param.quark_smearing.path);
01235                         
01236       }
01237       catch(const std::string& e) 
01238       {
01239         QDPIO::cerr << ": Caught Exception creating quark smearing object: " << e << endl;
01240         QDP_abort(1);
01241       }
01242       catch(...)
01243       {
01244         QDPIO::cerr << ": Caught generic exception creating smearing object" << endl;
01245         QDP_abort(1);
01246       }
01247 
01248       //
01249       // Meson operators
01250       //
01251 
01252       //We make all source operators before we make all sink operators to 
01253       //save on memory. 
01254 
01255       for(int t0 = 0; t0 < participating_timeslices.size() ; ++t0)
01256       {
01257         StopWatch watch;
01258 
01259         // Bummer. We have to hold both the smeared sources and the smeared
01260         // solutions simultaneously since the operator construction might
01261         // involve both the sources and the solutions in one operator
01262         // for either the creation and/or annihilation operator
01263 
01264         // The object holding the smeared and displaced color vector maps  
01265         SmearedDispObjects smrd_disp_vecs(params.param.displacement_length,
01266                                           diluted_quarks, quarkSmearing, u_smr);
01267 
01268         //Make the source operators 
01269         {
01270           // Creation operator
01271           MesonOperator_t  creat_oper;
01272           creat_oper.op_contract_type = params.param.creat_op_contract_type;
01273           creat_oper.mom2_max    = params.param.mom2_max;
01274           creat_oper.decay_dir   = decay_dir;
01275           creat_oper.seed_l      = diluted_quarks[1]->getSeed();
01276           creat_oper.seed_r      = diluted_quarks[0]->getSeed();
01277           creat_oper.dilution_l  = params.param.quark_dils[1];
01278           creat_oper.dilution_r  = params.param.quark_dils[0];
01279           creat_oper.smearing    = params.param.quark_smearing;
01280           creat_oper.time_slices.resize( 1 ); //Only a single t0 per file 
01281 
01282           // Construct creation operator
01283           // Loop over each operator 
01284           for(int l=0; l < qqq_oplist.ops.size(); ++l)
01285           {
01286             QDPIO::cout << "Elemental operator: op = " << l << endl;
01287 
01288             push(xml_out, "MesonOperator");
01289 
01290             creat_oper.id = qqq_oplist.ops[l].name;
01291 
01292             write(xml_out, "Name", creat_oper.id);
01293 
01294             // Build the operator
01295             swiss.reset();
01296             swiss.start();
01297 
01298             // The keys for the spin and displacements for this particular elemental operator
01299             multi1d<KeySmearedDispColorVector_t> keySmearedDispColorVector(N_quarks);
01300 
01301             for(int n = 0 ; n < N_quarks ; ++n)
01302             {
01303               keySmearedDispColorVector[n].displacement = qqq_oplist.ops[l].quark[n].displacement;
01304               keySmearedDispColorVector[n].spin         = qqq_oplist.ops[l].quark[n].spin;
01305             }
01306 
01307 
01308             creat_oper.time_slices[0].t0 = participating_timeslices[t0];
01309 
01310             const int n0 = 1;
01311             const int n1 = 0;
01312 
01313             // The operator must hold all the dilutions
01314 
01315             // Creation operator
01316             MesonOperator_t::TimeSlices_t& cop = creat_oper.time_slices[0];
01317 
01318             cop.dilutions.resize(diluted_quarks[n0]->getDilSize(t0), diluted_quarks[n1]->getDilSize(t0));
01319 
01320             for (int n = 0 ; n < N_quarks ; ++n)
01321             {
01322               keySmearedDispColorVector[n].t0 = t0;
01323             }
01324 
01325             for(int i = 0 ; i <  diluted_quarks[n0]->getDilSize(t0) ; ++i)
01326             {
01327               for(int j = 0 ; j < diluted_quarks[n1]->getDilSize(t0) ; ++j)
01328               {
01329                 keySmearedDispColorVector[0].dil = i;
01330                 keySmearedDispColorVector[1].dil = j;
01331 
01332                 LatticeComplex c_oper;
01333         
01334                 watch.reset();
01335                 watch.start();
01336 
01337                 // Do the relevant quark contraction
01338                 // Slow fourier-transform
01339                 // We can restrict what the FT routine requires to a subset.
01340                 multi2d<DComplex> c_sum(contractOp(smrd_disp_vecs,
01341                                                    n0, keySmearedDispColorVector[0],
01342                                                    n1, keySmearedDispColorVector[1],
01343                                                    params.param.creat_op_contract_type,
01344                                                    phases,
01345                                                    participating_timeslices[t0]));
01346                   
01347                 watch.stop();
01348 
01349                 /*QDPIO::cout << " Spatial sums completed: time = " << 
01350                   watch.getTimeInSeconds() << "secs " << endl;
01351                 */
01352                 // Unpack into separate momentum and correlator
01353                 cop.dilutions(i,j).mom_projs.resize(phases.numMom());
01354 
01355                 for(int mom_num = 0 ; mom_num < phases.numMom() ; ++mom_num) 
01356                 {
01357                   cop.dilutions(i,j).mom_projs[mom_num].mom = phases.numToMom(mom_num);
01358                   cop.dilutions(i,j).mom_projs[mom_num].op.resize(1);
01359 
01360                   cop.dilutions(i,j).mom_projs[mom_num].op[ 0 ] = 
01361                     c_sum[mom_num][ participating_timeslices[t0] ];
01362                 }
01363               } // end for j
01364             } // end for i
01365 
01366             swiss.stop();
01367 
01368 
01369             QDPIO::cout << "Creation operator construction: operator= " << l 
01370                         << "  time= "
01371                         << swiss.getTimeInSeconds() 
01372                         << " secs" << endl;
01373 
01374             QDPIO::cout << "Creation operator testval(t0 = " << 
01375               participating_timeslices[t0] << ") = " << 
01376               creat_oper.time_slices[0].dilutions(0,0).mom_projs[0].op[0]
01377                         << endl;
01378 
01379             //Hard code the elemental op name for now 
01380             std::stringstream cnvrt;
01381             cnvrt <<  creat_oper.id  << "_t" << participating_timeslices[t0] << "_src.lime";
01382 
01383             std::string filename;
01384 
01385             filename = cnvrt.str(); 
01386 
01387             // Write the meta-data and the binary for this operator
01388             swiss.reset();
01389             swiss.start();
01390             {
01391               XMLBufferWriter     src_record_xml, file_xml;
01392               BinaryBufferWriter  src_record_bin;
01393 
01394               push(file_xml, "SourceMesonOperator");
01395               write(file_xml, "Params", params.param);
01396               write(file_xml, "Config_info", gauge_xml);
01397               write(file_xml, "Op_Info",qqq_oplist.ops[l]);
01398 
01399               push(file_xml, "QuarkSources");
01400 
01401               const int n0 = 1;
01402               const int n1 = 0;
01403 
01404               push(file_xml, "Quark_l");
01405               push(file_xml, "TimeSlice");
01406               push(file_xml, "Dilutions");
01407               for (int dil = 0; dil < diluted_quarks[n0]->getDilSize(t0) ; ++dil)
01408               {
01409                 write(file_xml, "elem", diluted_quarks[n0]->getSourceHeader(t0, dil));
01410 
01411                 //      QDPIO::cout<< "t0 = " << t0 << " dil = "<< dil <<
01412                 //      " srdhdr = XX"<<diluted_quarks[n0]->getSourceHeader(t0,dil) << endl;
01413               }
01414               pop(file_xml); //dilutions 
01415               pop(file_xml); //TimeSlice
01416               pop(file_xml); //Quark_l
01417 
01418               push(file_xml, "Quark_r");
01419               push(file_xml, "TimeSlice");
01420               push(file_xml, "Dilutions");
01421               for (int dil = 0; dil < diluted_quarks[n1]->getDilSize(t0) ; ++dil)
01422               {
01423                 write(file_xml, "elem", diluted_quarks[n1]->getSourceHeader(t0, dil));
01424               }
01425               pop(file_xml); //dilutions 
01426               pop(file_xml); //TimeSlice
01427               pop(file_xml); //Quark_r
01428 
01429               pop(file_xml);//QuarkSources
01430               push(file_xml, "QuarkSinks");
01431 
01432               push(file_xml, "Quark_l");
01433               write(file_xml, "PropHeader", diluted_quarks[n0]->getPropHeader(0,0));
01434               pop(file_xml);
01435 
01436               push(file_xml, "Quark_r");
01437               write(file_xml, "PropHeader", diluted_quarks[n1]->getPropHeader(0,0));
01438               pop(file_xml);
01439 
01440               pop(file_xml); //Quark Sinks  
01441               pop(file_xml);//SourceMesonOp
01442 
01443               QDPFileWriter qdp_file(file_xml, filename,     // are there one or two files???
01444                                      QDPIO_SINGLEFILE, QDPIO_SERIAL, QDPIO_OPEN);
01445 
01446 
01447               write(src_record_xml, "MesonCreationOperator", creat_oper);
01448               write(src_record_bin, creat_oper);
01449 
01450               write(qdp_file, src_record_xml, src_record_bin);
01451 
01452             }
01453             swiss.stop();
01454 
01455             QDPIO::cout << "Source Operator writing: operator = " << 
01456               l << "  time= "
01457                         << swiss.getTimeInSeconds() 
01458                         << " secs" << endl;
01459 
01460             pop(xml_out); // MesonOperator 
01461 
01462           } // end for l (operator )
01463 
01464         } //End Make creation operator
01465 
01466 
01467 
01468         //Make Annilation Operator
01469         {
01470           // Annihilation operator
01471           MesonOperator_t  annih_oper;
01472           annih_oper.op_contract_type = params.param.annih_op_contract_type;
01473           annih_oper.mom2_max    = params.param.mom2_max;
01474           annih_oper.decay_dir   = decay_dir;
01475           annih_oper.seed_l      = diluted_quarks[0]->getSeed();
01476           annih_oper.seed_r      = diluted_quarks[1]->getSeed();
01477           annih_oper.dilution_l  = params.param.quark_dils[0];
01478           annih_oper.dilution_r  = params.param.quark_dils[1];
01479           annih_oper.smearing    = params.param.quark_smearing;
01480           annih_oper.time_slices.resize( 1 );
01481 
01482           // Construct annihilation operator
01483           QDPIO::cout << "Building Sink operators" << endl;
01484 
01485           // Loop over each operator 
01486           for(int l=0; l < qqq_oplist.ops.size(); ++l)
01487           {
01488             QDPIO::cout << "Elemental operator: op = " << l << endl;
01489 
01490             annih_oper.id = qqq_oplist.ops[l].name;
01491 
01492             // Build the operator
01493             swiss.reset();
01494             swiss.start();
01495 
01496             // The keys for the spin and displacements for this particular elemental operator
01497             multi1d<KeySmearedDispColorVector_t> keySmearedDispColorVector(N_quarks);
01498 
01499             for(int n = 0 ; n < N_quarks ; ++n)
01500             {
01501               keySmearedDispColorVector[n].displacement = qqq_oplist.ops[l].quark[n].displacement;
01502               keySmearedDispColorVector[n].spin         = qqq_oplist.ops[l].quark[n].spin;
01503             }
01504 
01505             annih_oper.time_slices[0].t0 = participating_timeslices[t0];
01506 
01507             const int n0 = 0;
01508             const int n1 = 1;
01509 
01510             // The operator must hold all the dilutions
01511             // We know that all time slices match. However, not all time slices of the
01512             // lattice maybe used
01513 
01514             // Annihilation operator
01515             MesonOperator_t::TimeSlices_t& aop = annih_oper.time_slices[0];
01516 
01517             aop.dilutions.resize(diluted_quarks[n0]->getDilSize(t0), diluted_quarks[n1]->getDilSize(t0));
01518 
01519             for (int n = 0 ; n < N_quarks ; ++n)
01520             {
01521               keySmearedDispColorVector[n].t0 = t0;
01522             }
01523 
01524             for(int i = 0 ; i <  diluted_quarks[n0]->getDilSize(t0) ; ++i)
01525             {
01526               for(int j = 0 ; j < diluted_quarks[n1]->getDilSize(t0) ; ++j)           
01527               {
01528                 keySmearedDispColorVector[0].dil = i;
01529                 keySmearedDispColorVector[1].dil = j;
01530 
01531                 watch.reset();
01532                 watch.start();
01533 
01534                 // Contract over color indices
01535                 // Do the relevant quark contraction
01536                 // Slow fourier-transform
01537                 // We can restrict what the FT routine requires to a subset.
01538                 multi2d<DComplex> a_sum(contractOp(smrd_disp_vecs,
01539                                                    n0, keySmearedDispColorVector[0],
01540                                                    n1, keySmearedDispColorVector[1],
01541                                                    params.param.annih_op_contract_type,
01542                                                    phases,
01543                                                    participating_timeslices[t0]));
01544                   
01545                 watch.stop();
01546                 /*
01547                   QDPIO::cout << "Spatial Sums completed: time " << 
01548                   watch.getTimeInSeconds() << "secs" << endl;
01549                 */              
01550                 // Unpack into separate momentum and correlator
01551                 aop.dilutions(i,j).mom_projs.resize(phases.numMom());
01552 
01553                 for(int mom_num = 0 ; mom_num < phases.numMom() ; ++mom_num) 
01554                 {
01555                   aop.dilutions(i,j).mom_projs[mom_num].mom = phases.numToMom(mom_num);
01556 
01557                   aop.dilutions(i,j).mom_projs[mom_num].op = a_sum[mom_num];
01558                 }
01559               } // end for j
01560             } // end for i
01561             swiss.stop();
01562 
01563 
01564             QDPIO::cout << "Annihilation operator construction: operator= " << l 
01565                         << "  time= "
01566                         << swiss.getTimeInSeconds() 
01567                         << " secs" << endl;
01568 
01569             QDPIO::cout << "Annihilation op testval( t0 = " << 
01570               participating_timeslices[t0] << ") = " << 
01571               annih_oper.time_slices[0].dilutions(0,0).mom_projs[0].op[0] 
01572                         << endl;
01573 
01574             //Hard code the elemental op name for now 
01575             std::stringstream cnvrt;
01576             cnvrt <<  annih_oper.id  << "_t" << participating_timeslices[t0] << "_snk.lime";
01577 
01578             std::string filename;
01579 
01580             filename = cnvrt.str(); 
01581 
01582             // Write the meta-data and the binary for this operator
01583             swiss.reset();
01584             swiss.start();
01585             {
01586               XMLBufferWriter     src_record_xml, file_xml;
01587               BinaryBufferWriter  src_record_bin;
01588 
01589               push(file_xml, "SinkMesonOperator");
01590               write(file_xml, "Params", params.param);
01591               write(file_xml, "Config_info", gauge_xml);
01592               write(file_xml, "Op_Info",qqq_oplist.ops[l]);
01593               push(file_xml, "QuarkSources");
01594 
01595               const int n0 = 0;
01596               const int n1 = 1;
01597 
01598               push(file_xml, "Quark_l");
01599               push(file_xml, "TimeSlice");
01600               push(file_xml, "Dilutions");
01601               for (int dil = 0; dil < diluted_quarks[n0]->getDilSize(t0) ; ++dil)
01602               {
01603                 write(file_xml, "elem", diluted_quarks[n0]->getSourceHeader(t0, dil));
01604               }
01605               pop(file_xml); //dilutions 
01606               pop(file_xml); //TimeSlice
01607               pop(file_xml); //Quark_l
01608 
01609               push(file_xml, "Quark_r");
01610               push(file_xml, "TimeSlice");
01611               push(file_xml, "Dilutions");
01612               for (int dil = 0; dil < diluted_quarks[n1]->getDilSize(t0) ; ++dil)
01613               {
01614                 write(file_xml, "elem", diluted_quarks[n1]->getSourceHeader(t0, dil));
01615               }
01616               pop(file_xml); //dilutions 
01617               pop(file_xml); //TimeSlice
01618               pop(file_xml); //Quark_r
01619 
01620               pop(file_xml);//QuarkSources
01621               push(file_xml, "QuarkSinks");
01622 
01623               push(file_xml, "Quark_l");
01624               write(file_xml, "PropHeader", diluted_quarks[n0]->getPropHeader(0,0));
01625               pop(file_xml);
01626 
01627               push(file_xml, "Quark_r");
01628               write(file_xml, "PropHeader", diluted_quarks[n1]->getPropHeader(0,0));
01629               pop(file_xml);
01630 
01631               pop(file_xml);//QuarkSinks 
01632               pop(file_xml);//SinkMesonOperator
01633 
01634               QDPFileWriter qdp_file(file_xml, filename,     // are there one or two files???
01635                                      QDPIO_SINGLEFILE, QDPIO_SERIAL, QDPIO_OPEN);
01636 
01637 
01638               write(src_record_xml, "MesonAnnihilationOperator", annih_oper);
01639               write(src_record_bin, annih_oper);
01640 
01641               write(qdp_file, src_record_xml, src_record_bin);
01642 
01643             }
01644             swiss.stop();
01645 
01646             QDPIO::cout << "Annihilation Operator writing: operator = " << l
01647                         << "  time= " << swiss.getTimeInSeconds() << " secs" << endl;
01648 
01649           } // end for l (operator )
01650 
01651         } //End Make annihilation operator
01652 
01653       } //end t0 
01654 
01655       // Close the namelist output file XMLDAT
01656       pop(xml_out);     // StochMeson
01657 
01658       snoop.stop();
01659       QDPIO::cout << InlineStochGroupMesonEnv::name << ": total time = " 
01660                   << snoop.getTimeInSeconds() 
01661                   << " secs" << endl;
01662 
01663       QDPIO::cout << InlineStochGroupMesonEnv::name << ": ran successfully" << endl;
01664 
01665       END_CODE();
01666     } // func
01667 
01668   } // namespace InlineStochGroupMesonEnv
01669 
01670   /*! @} */  // end of group hadron
01671 
01672 } // namespace Chroma

Generated on Sun Nov 22 04:33:14 2009 for CHROMA by  doxygen 1.4.7