CHROMA
inline_disco_eigcg_w.cc
Go to the documentation of this file.
1 
2 /*! \file
3  * \brief Inline measurement 3pt_prop
4  *
5  * This version does not use e/o preconditioning on the noise vectors,
6  * but it does for the eigcg pieces, as it must.
7  *
8  */
9 
10 #include "handle.h"
19 #include "meas/sources/zN_src.h"
25 #include "meas/hadron/barQll_w.h"
28 #include "meas/glue/mesplq.h"
29 #include "util/ft/sftmom.h"
30 #include "util/info/proginfo.h"
32 #include "util/info/unique_id.h"
33 #include "util/ferm/transf.h"
35 
38 
41 
45 
46 #include "util/ferm/key_val_db.h"
47 
48 #include <qdp-lapack.h>
49 #include <qdp_config.h>
50 
51 #include <vector>
52 #include <map>
53 
54 
55 namespace Chroma{
56  namespace InlineDiscoEigCGEnv{
57  namespace{
58  AbsInlineMeasurement* createMeasurement(XMLReader& xml_in,
59  const std::string& path)
60  {
61  return new InlineMeas(Params(xml_in, path));
62  }
63 
64  //! Local registration flag
65  bool registered = false;
66  }
67 
68  const std::string name = "DISCO_EIGCG";
69 
70  //! Register all the factories
71  bool registerAll()
72  {
73  bool success = true;
74  if (! registered)
75  {
76  //success &= BaryonOperatorEnv::registerAll();
77  success &= TheInlineMeasurementFactory::Instance().registerObject(name, createMeasurement);
78  registered = true;
79  }
80  return success;
81  }
82 
83  // Reader for input parameters
84  void read(XMLReader& xml, const std::string& path, Params::Param_t& param){
85  XMLReader paramtop(xml, path);
86 
87  int version;
88  read(paramtop, "version", version);
89 
90  switch (version)
91  {
92  case 1:
93  /************************************************************/
94  read(paramtop,"max_path_length",param.max_path_length);
95  read(paramtop,"p2_max",param.p2_max);
96  read(paramtop,"mass_label",param.mass_label);
97  param.chi = readXMLArrayGroup(paramtop, "Quarks", "DilutionType");
98  param.action = readXMLGroup(paramtop, "FermionAction","FermAct");
99 
100  break;
101 
102  default :
103  /**************************************************************/
104 
105  QDPIO::cerr << "Input parameter version " << version << " unsupported." << std::endl;
106  QDP_abort(1);
107  }
108  }
109 
110  // Writer for input parameters
111  void write(XMLWriter& xml, const std::string& path, const Params::Param_t& param){
112  push(xml, path);
113 
114  int version = 1;
115 
116  write(xml, "version", version);
117 
118  write(xml,"max_path_length",param.max_path_length);
119  write(xml,"p2_max",param.p2_max);
120  write(xml,"mass_label",param.mass_label);
121  push(xml,"FermionAction");
122  xml<<param.action.xml ;
123  pop(xml);
124  push(xml,"Quarks");
125  for( int t(0);t<param.chi.size();t++){
126  push(xml,"elem");
127  xml<<param.chi[t].xml;
128  pop(xml);
129  }
130  pop(xml);
131 
132  pop(xml); // final pop
133  }
134 
135  //! Gauge field parameters
136  void read(XMLReader& xml, const std::string& path, Params::NamedObject_t& input)
137  {
138  XMLReader inputtop(xml, path);
139 
140  read(inputtop, "gauge_id" , input.gauge_id ) ;
141  // If no file is included, then we will turn off the eig_cg part (ie, use 0 vectors)
142  if ( inputtop.count("evecs_file")!=0 )
143  read(inputtop, "evecs_file" , input.evecs_file ) ;
144  else
145  input.evecs_file="";
146 
147  read(inputtop, "op_db_file" , input.op_db_file ) ;
148  }
149 
150  //! Gauge field parameters
151  void write(XMLWriter& xml, const std::string& path, const Params::NamedObject_t& input){
152  push(xml, path);
153 
154  write(xml, "gauge_id" , input.gauge_id );
155  write(xml, "evecs_file" , input.evecs_file );
156  write(xml, "op_db_file" , input.op_db_file );
157  pop(xml);
158  }
159 
160 
161  // Param stuff
163  frequency = 0;
164  }
165 
166  Params::Params(XMLReader& xml_in, const std::string& path)
167  {
168  try
169  {
170  XMLReader paramtop(xml_in, path);
171 
172  if (paramtop.count("Frequency") == 1)
173  read(paramtop, "Frequency", frequency);
174  else
175  frequency = 1;
176 
177  // Read program parameters
178  read(paramtop, "Param", param);
179 
180  // Read in the output propagator/source configuration info
181  read(paramtop, "NamedObject", named_obj);
182 
183  // Possible alternate XML file pattern
184  if (paramtop.count("xml_file") != 0)
185  {
186  read(paramtop, "xml_file", xml_file);
187  }
188  }
189  catch(const std::string& e)
190  {
191  QDPIO::cerr << __func__ << ": Caught Exception reading XML: " << e << std::endl;
192  QDP_abort(1);
193  }
194  }
195 
196 
197  void Params::write(XMLWriter& xml_out, const std::string& path)
198  {
199  push(xml_out, path);
200 
201  // Parameters for source construction
202  InlineDiscoEigCGEnv::write(xml_out, "Param", param);
203 
204  // Write out the output propagator/source configuration info
205  InlineDiscoEigCGEnv::write(xml_out, "NamedObject", named_obj);
206 
207  pop(xml_out);
208  }
209 
210 
211  //! Meson operator
213  {
214  multi1d<short int> mom ; /*!< D-1 momentum of this operator */
215  unsigned short int t_slice ; /*!< Meson operator time slice */
216  multi1d<short int> disp ; /*!< Displacement dirs of quark (right)*/
217 
219  mom.resize(Nd-1);
220  }
221  };
222 
223  bool operator<(const KeyOperator_t& a, const KeyOperator_t& b){
224  return ((a.t_slice<b.t_slice)||(a.mom<b.mom)||(a.disp<b.disp));
225  }
226 
227  std::ostream& operator<<(std::ostream& os, const KeyOperator_t& d)
228  {
229  os << "KeyOperator_t:"
230  << " t_slice = " << d.t_slice
231  << ", disp = ";
232  for (int i=0; i<d.disp.size();i++)
233  os << d.disp[i] << " " ;
234 
235  os << ", mom = ";
236  for (int i=0; i<d.mom.size();i++)
237  os << d.mom[i] << " " ;
238 
239  os << std::endl;
240 
241  return os;
242  }
243 
245  public:
246  multi1d<ComplexD> op ;
247  ValOperator_t(){op.resize(Ns*Ns);} // Here go the 16 gamma matrices
249  } ;
250 
251  //-------------------------------------------------------------------------
252  //! stream IO
253  std::ostream& operator<<(std::ostream& os, const ValOperator_t& d)
254  {
255  os << "ValOperator_t:\n";
256  for (int i=0; i<d.op.size();i++)
257  os <<" gamma["<<i<<"] = "<< d.op[i] << std::endl ;
258 
259  return os;
260  }
261 
262  struct KeyVal_t{
265  };
266 
267  //! KeyOperator reader
268  void read(BinaryReader& bin, KeyOperator_t& d){
269  read(bin,d.t_slice);
270  unsigned short int n ;
271  read(bin,n);
272  d.disp.resize(n);
273  read(bin,d.disp);
274  d.mom.resize(Nd-1) ;
275  read(bin,d.mom);
276  }
277  //! KeyOperator writer
278  void write(BinaryWriter& bin, const KeyOperator_t& d){
279  write(bin,d.t_slice);
280  unsigned short int n ;
281  n = d.disp.size();
282  write(bin,n);
283  write(bin,d.disp);
284  write(bin,d.mom);
285  }
286 
287  //! ValOperator reader
288  void read(BinaryReader& bin, ValOperator_t& d){
289  d.op.resize(Ns*Ns);
290  read(bin,d.op);
291  }
292  //! ValOperator writer
293  void write(BinaryWriter& bin, const ValOperator_t& d){
294  write(bin,d.op);
295  }
296 
297  namespace{
298  StandardOutputStream& operator<<(StandardOutputStream& os, const multi1d<short int>& d){
299  if (d.size() > 0){
300  os << d[0];
301  for(int i=1; i < d.size(); i++)
302  os << " " << d[i];
303  }
304  return os;
305  }
306  }
307 
308  // Set t0set;
309  // t0set.make(TimeSliceFunc(Nd-1));
310 
311  // Set timerb;
312  // timerb.make(TimeSliceRBFunc(Nd-1));
313 
314  typedef LatticeFermion T;
315  typedef multi1d<LatticeColorMatrix> P;
316  typedef multi1d<LatticeColorMatrix> Q;
317 
319  createOddOdd_Op( const Params::Param_t& param, const P& u){
320  //
321  // Initialize fermion action
322  //
323  std::istringstream xml_s(param.action.xml);
324  XMLReader fermacttop(xml_s);
325  QDPIO::cout << "FermAct = " << param.action.id << std::endl;
326  //
327  // Try the factories
328  //
330  try{
331  QDPIO::cout << "Try the various Wilson fermion factories" << std::endl;
332  // Generic Wilson-Type stuff
334  Sf(TheFermionActionFactory::Instance().createObject(param.action.id,
335  fermacttop,
336  param.action.path));
337  state = Sf->createState(u);//got the state
338  QDPIO::cout << "Suitable factory found: compute the trace quark prop"<<std::endl;
339  }
340  catch (const std::string& e){
341  QDPIO::cout << name
342  << ": caught exception instantiating the action: " << e << std::endl;
343  }
344 
345  // Now need to construct the operator
346  // this seems tricky and maybe there is a better way... (Robert-Balint help!)
347  // We only work with Wilson and Clover Wilson fermions so check the following 2
348  // For the moment we restrict to EO preconditioned only
349 
350  //this is the Odd-Odd piece
352  if(param.action.id == "WILSON"){
353  WilsonFermActParams wp(fermacttop,param.action.path);
354  return new EvenOddPrecWilsonLinOp(state,wp.Mass,wp.anisoParam ) ;
355  }
356  else if(param.action.id == "CLOVER"){
357  CloverFermActParams cp(fermacttop,param.action.path);
358  return new EvenOddPrecCloverLinOp(state,cp) ;
359  }
360  else{
361  QDPIO::cout<<name<<" : Tough luck dude! No code for you..."<<std::endl ;
362  QDP_abort(1);
363  }
364  return NULL ;
365  }
366 
368  multi1d<Real> evals ;
369  multi1d<Complex> H ;
370  multi1d<Complex> HU ;
371  int ldh ;
372  int Nvec ;
373  } ;
374 
375  void do_disco(std::map< KeyOperator_t, ValOperator_t >& db,
376  const LatticeFermion& qbar,
377  const LatticeFermion& q,
378  const SftMom& p,
379  const int& t,
380  const multi1d<short int>& path,
381  const int& max_path_length ){
382  QDPIO::cout<<" Computing Operator with path length "<<path.size()
383  <<" on timeslice "<<t<<". Path: "<<path <<std::endl;
384  ValOperator_t val ;
385  KeyOperator_t key ;
386  std::pair<KeyOperator_t, ValOperator_t> kv ;
387  kv.first.t_slice = t ;
388  if(path.size()==0){
389  kv.first.disp.resize(1);
390  kv.first.disp[0] = 0 ;
391  }
392  else
393  kv.first.disp = path ;
394 
395  multi1d< multi1d<ComplexD> > foo(p.numMom()) ;
396  for (int m(0); m < p.numMom(); m++)
397  foo[m].resize(Ns*Ns);
398  for(int g(0);g<Ns*Ns;g++){
399  LatticeComplex cc = localInnerProduct(qbar,Gamma(g)*q);
400  for (int m(0); m < p.numMom(); m++){
401  foo[m][g] = sum(p[m]*cc,p.getSet()[t]);
402  }
403  }
404  for (int m(0); m < p.numMom(); m++){
405  for(int i(0);i<(Nd-1);i++)
406  kv.first.mom[i] = p.numToMom(m)[i] ;
407 
408  kv.second.op = foo[m];
409  std::pair<std::map< KeyOperator_t, ValOperator_t >::iterator, bool> itbo;
410 
411  itbo = db.insert(kv);
412  if( itbo.second ){
413  QDPIO::cout<<"Inserting new entry in std::map\n";
414  }
415  else{ // if insert fails, key already exists, so add result
416  for(int i(0);i<kv.second.op.size();i++)
417  itbo.first->second.op[i] += kv.second.op[i] ;
418  }
419  }//m
420 
421  if(path.size()<max_path_length){
422  QDPIO::cout<<" attempt to add new path. "
423  <<" current path length is : "<<path.size();
424  multi1d<short int> new_path(path.size()+1);
425  QDPIO::cout<<" new path length is : "<<new_path.size()<<std::endl;
426  for(int i(0);i<path.size();i++)
427  new_path[i] = path[i] ;
428  for(int sign(-1);sign<2;sign+=2)
429  for(int mu(0);mu<Nd;mu++){
430  new_path[path.size()]= sign*(mu+1) ;
431  //skip back tracking
432  bool back_track=false ;
433  if(path.size()>0)
434  if(path[path.size()-1] == -new_path[path.size()])
435  back_track=true;
436  if(!back_track){
437  QDPIO::cout<<" Added path: "<<new_path<<std::endl;
438  LatticeFermion q_mu ;
439  if(sign>0)
440  q_mu = shift(q, FORWARD, mu);
441  else
442  q_mu = shift(q, BACKWARD, mu);
443 
444  do_disco(db, qbar, q_mu, p, t, new_path, max_path_length);
445  } // skip backtracking
446  } // mu
447  }// path.size loop
448 
449  }// do_disco
450 
451  void do_disco(std::map< KeyOperator_t, ValOperator_t >& db,
452  CholeskyFactors Clsk ,
453  multi1d<LatticeFermion>& vec,
454  const Params::Param_t& param,
456  const P& u,
457  const int& t,
458  const Subset& trb,
459  const SftMom& p,
460  const multi1d<short int>& path){
461 
462  QDPIO::cout<<" Computing Operator with path length "<<path.size()
463  <<" on timeslice "<<t<<". Path: "<<path <<std::endl;
464  int max_path_length = param.max_path_length;
465 
466  ValOperator_t val ;
467  KeyOperator_t key ;
468  std::pair<KeyOperator_t, ValOperator_t> kv ;
469 
470  kv.first.t_slice = t ;
471  if(path.size()==0){
472  kv.first.disp.resize(1);
473  kv.first.disp[0] = 0 ;
474  }
475  else
476  kv.first.disp = path ;
477 
478  int ldb = vec.size();
479  int info;
480  char U = 'U';
481  int Nrhs = ldb; // Because we have no dilution vectors, but rhs's are made of EigCG vecs...
482  multi2d<Complex> B(Nrhs,ldb);
483  /*
484  multi1d< multi1d<LatticeFermion> > DDvec(ldb);
485  // Zero out the fermions
486  for(int i(0); i<ldb;i++){
487  DDvec[i].resize(Ns*Ns);
488  DDvec[i] = zero;
489  }
490  std::cout<<"We've initialized DDvec!\n";
491 
492  for(int i(0); i<ldb;i++){
493  LatticeFermion qtmp = zero ;
494  LatticeFermion qtmp2 = zero ;
495  LatticeFermion qtmp3 = zero ;
496  Doo->evenOddLinOp(qtmp,vec[i],PLUS);
497  Doo->evenEvenInvLinOp(qtmp2,qtmp,PLUS);
498  for(int g(0);g<Ns*Ns;g++){
499  Doo->evenEvenInvLinOp(qtmp3,Gamma(g)*qtmp2,PLUS);
500  qtmp = zero;
501  qtmp2 = zero;
502  Doo->oddEvenLinOp(qtmp,qtmp3,PLUS);
503  Doo->oddOddLinOp(qtmp2,qtmp,MINUS);
504  qtmp = zero;
505  Doo->oddOddLinOp(qtmp,Gamma(g)*vec[i],MINUS);
506  // I think this could run into memory problems with too many vectors
507  DDvec[i][g] = qtmp + qtmp2;
508  }
509  }
510  */
511  multi1d< multi1d<ComplexD> > foo(p.numMom()) ;
512  for (int m(0); m < p.numMom(); m++){
513  foo[m].resize(Ns*Ns);
514  foo[m] = zero;
515  }
516  // Okay, this is probably inefficient, b/c we are doing some things multiple times...
517  multi1d< LatticeFermion > Svec(ldb);
518  multi1d< LatticeFermion > DDvec(ldb);
519  multi1d< LatticeFermion > DDSvec(ldb);
520  Svec = zero;
521  DDvec = zero;
522  for(int i(0); i<ldb;i++){
523  LatticeFermion qtmp = zero ;
524  // DeeInv * Deo * V:
525  Doo->evenOddLinOp(qtmp, vec[i],PLUS);
526  Doo->evenEvenInvLinOp(DDvec[i], qtmp,PLUS);
527  qtmp = zero;
528  //DeeInv^dag * Deo^dag * Soo * V:
529  Doo->oddOddLinOp(qtmp,vec[i],PLUS);
530  LatticeFermion qtmp2 = zero;
531  Doo->evenOddLinOp(qtmp2,qtmp,MINUS);
532  Doo->evenEvenInvLinOp(DDSvec[i],qtmp2,MINUS);
533  // Soo * V
534  Doo->oddOddLinOp(Svec[i],vec[i],PLUS);
535  }
536 
537  for(int g(0);g<Ns*Ns;g++){
538  for (int m(0); m < p.numMom(); m++){
539  for (int i(0); i<ldb;i++){
540  for (int j(0); j<ldb;j++){
541  LatticeComplex cc1 = localInnerProduct(Svec[j],Gamma(g)*vec[i]);
542  LatticeComplex cc2 = localInnerProduct(DDSvec[j],Gamma(g)*DDvec[i]);
543  B[i][j] = sum(p[m]*(cc1+cc2),trb) ;
544  // B[i][j] = sum(p[m]*(cc1+cc2),rb[1]) ;
545  }//j
546  }//i
547 
548 #if BASE_PRECISION == 32
549  int r = QDPLapack::cpotrs(U, Clsk.Nvec, Nrhs, Clsk.HU, Clsk.ldh, B, ldb, info);
550 #else
551  int r = QDPLapack::zpotrs(U, Clsk.Nvec, Nrhs, Clsk.HU, Clsk.ldh, B, ldb, info);
552 #endif
553 
554  // and at this point, B is H^-1 Vdag Sdag gamma V, so
555  // For debugging purposes, both r and info should be zero...
556  QDPIO::cout<<"do_disco cpotrs r = "<<r<<std::endl;
557  QDPIO::cout<<"do_disco cpotrs info = "<<info<<std::endl;
558 
559  for (int i(0); i<ldb;i++){
560  foo[m][g] += ComplexD(B[i][i]);// Trace over last set of indices
561  }
562  }//m
563  }//g
564  for (int m(0); m < p.numMom(); m++){
565  for(int i(0);i<(Nd-1);i++)
566  kv.first.mom[i] = p.numToMom(m)[i] ;
567 
568  kv.second.op = foo[m];
569 
570  std::pair<std::map< KeyOperator_t, ValOperator_t >::iterator, bool> itbo;
571 
572  itbo = db.insert(kv);
573  if( !(itbo.second) ){ // if insert fails, key already exists, so add result
574  for(int i(0);i<kv.second.op.size();i++)
575  itbo.first->second.op[i] += kv.second.op[i] ;
576  }
577  else
578  QDPIO::cout<<"Inserting new entry in std::map\n";
579  }
580 
581  if(path.size()<max_path_length){
582  QDPIO::cout<<" attempt to add new path. "
583  <<" current path length is : "<<path.size();
584  multi1d<short int> new_path(path.size()+1);
585  QDPIO::cout<<" new path length is : "<<new_path.size()<<std::endl;
586  for(int i(0);i<path.size();i++)
587  new_path[i] = path[i] ;
588  for(int sign(-1);sign<2;sign+=2)
589  for(int mu(0);mu<Nd;mu++){
590  new_path[path.size()]= sign*(mu+1) ;
591  //skip back tracking
592  bool back_track=false ;
593  if(path.size()>0)
594  if(path[path.size()-1] == -new_path[path.size()])
595  back_track=true;
596  if(!back_track){
597  QDPIO::cout<<" Added path: "<<new_path<<std::endl;
598  multi1d<LatticeFermion> vec_mu(vec.size()) ;
599  for(int j(0);j<vec.size();j++){
600  if(sign>0)
601  vec_mu[j] = shift(vec[j], FORWARD, mu);
602  else
603  vec_mu[j] = shift(vec[j], BACKWARD, mu);
604  }
605  do_disco(db, Clsk , vec_mu, param, Doo, u, t, trb, p, new_path);
606  } // skip backtracking
607  } // mu
608  }// path.size loop
609  }// do_disco
610 
611 
612  void ReadOPTEigCGVecs(multi1d<LatticeFermion>& vec,
613  CholeskyFactors& Clsk,
614  const std::string& evecs_file)
615  {
616  QDPIO::cout<<name<<" : Reading vecs from "
617  << evecs_file <<std::endl ;
618  StopWatch swatch;
619  swatch.reset();
620  swatch.start();
621 
622  int Nvecs,ldh ;
623  // File XML
624  XMLReader file_xml;
625  // Open file
626  QDPFileReader to(file_xml,evecs_file,QDPIO_SERIAL);
627  read(file_xml, "/OptEigInfo/ncurEvals", Nvecs);
628  read(file_xml, "/OptEigInfo/ldh", ldh);
629  // Added Nvecs and ldh to the Cholesky structure for later...
630  Clsk.Nvec = Nvecs;
631  Clsk.ldh = ldh;
632  vec.resize(Nvecs);
633  Clsk.evals.resize(ldh);
634  Clsk.H.resize(ldh*ldh);
635  Clsk.HU.resize(ldh*ldh);
636 
637  for(int v(0);v<Nvecs;v++){
638  XMLReader record_xml;
639  read(to, record_xml, vec[v]);
640  }
641 
642  XMLReader record_xml;
643  read(to, record_xml, Clsk.evals);
644  read(to, record_xml, Clsk.H);
645  read(to, record_xml, Clsk.HU);
646  swatch.stop();
647  QDPIO::cout<<name<<" : Time to read vecs= "
648  << swatch.getTimeInSeconds() <<" secs "<<std::endl ;
649  }
650 
651  // PRchi returns chitilde = (1 - V Hinv Vdag Sdag S)chi given
652  // an input chi std::vector, and of course the vectors and H.
653  void PRchi(multi1d<multi1d< multi1d<LatticeFermion> > >& quarkstilde,
654  const multi1d< Handle< DilutionScheme<LatticeFermion> > >& quarks,
656  CholeskyFactors Clsk , multi1d<LatticeFermion>& vec,
657  const Params::Param_t& param, const P& u){
658  char U = 'U';
659  int info;
660 
661  int ldb = vec.size();//This is the offset that will for now be the size of each std::vector
662 
663  Set timerb;
664  timerb.make(TimeSliceRBFunc(3));
665 
666  // Now we have to create the Sdag * S * quarks object to put into B
667  for(int n(0);n<quarks.size();n++){
668  for (int it(0) ; it < quarks[n]->getNumTimeSlices() ; ++it){
669  int t = quarks[n]->getT0(it) ;
670  int Nrhs = quarks[n]->getDilSize(it) ;
671  multi2d<Complex> B(Nrhs, ldb);
672  for(int i(0); i<ldb;i++){
673  for(int j = 0 ; j < Nrhs ; j++){
674  /**
675  Here, we are calculating
676  Sdag S chi
677  where chi (the solution) is Sinv eta, and eta is the noise std::vector (the source)
678  Thus, we can save time by using the source, and calculate
679  Sdag eta,
680  and that's what is being done here
681  **/
682  LatticeFermion qsrc = quarks[n]->dilutedSource(it,j);
683  LatticeFermion SdagSchi = zero ;
684  Doo->oddOddLinOp(SdagSchi,qsrc,MINUS);
685  // Sum over (odd) lattice sites, so we return a complex number for B
686  // SHOULD THIS BE ONLY SITES THAT INCLUDE THE TIMESLICE WE'RE ON?
687  // Doesn't seem to matter, same answer either way.
688  B[j][i] = sum(localInnerProduct(vec[i],SdagSchi),rb[1]);
689  //B[j][i] = sum(localInnerProduct(vec[i],SdagSchi),timerb[2*t+1]);
690  }
691  }
692 
693 #if BASE_PRECISION == 32
694  int r = QDPLapack::cpotrs(U, Clsk.Nvec, Nrhs, Clsk.HU, Clsk.ldh, B, ldb, info);
695 #else
696  int r = QDPLapack::zpotrs(U, Clsk.Nvec, Nrhs, Clsk.HU, Clsk.ldh, B, ldb, info);
697 #endif
698  QDPIO::cout<<"PRchi cpotrs r = "<<r<<std::endl;
699  QDPIO::cout<<"PRchi cpotrs info = "<<info<<std::endl;
700 
701  for(int j = 0 ; j < Nrhs ; j++){
702  LatticeFermion vB = zero;
703  LatticeFermion q = quarks[n]->dilutedSolution(it,j);
704  for(int i(0); i<ldb;i++)
705  vB += B[j][i]*vec[i];
706  quarkstilde[n][it][j] = q - vB;
707  std::cout<<"Norm of PRchi: "<<norm2(quarkstilde[n][it][j])<<std::endl;
708  }
709  }
710  }
711  }// End of PRchi call...
712 
713  /**
714  This version is called if we have no EigCG vectors, so PR = 1
715  **/
716  void PRchi(multi1d<multi1d< multi1d<LatticeFermion> > >& quarkstilde,
717  multi1d< Handle< DilutionScheme<LatticeFermion> > >& quarks){
718 
719  for(int n(0);n<quarks.size();n++){
720  for (int it(0) ; it < quarks[n]->getNumTimeSlices() ; it++){
721  for (int j(0) ; j < quarks[n]->getDilSize(it) ; j++){
722  quarkstilde[n][it][j] = quarks[n]->dilutedSolution(it,j);
723  }
724  }
725  }
726  }// End of PRchi call...
727 
728  //--------------------------------------------------------------
729  // Function call
730  // void
731  //InlineDiscoEigCG::operator()(unsigned long update_no,
732  // XMLWriter& xml_out)
733  void InlineMeas::operator()(unsigned long update_no,
734  XMLWriter& xml_out)
735  {
736  // If xml file not empty, then use alternate
737  if (params.xml_file != ""){
738  std::string xml_file = makeXMLFileName(params.xml_file, update_no);
739 
740  push(xml_out, "discoEigCG");
741  write(xml_out, "update_no", update_no);
742  write(xml_out, "xml_file", xml_file);
743  pop(xml_out);
744 
745  XMLFileWriter xml(xml_file);
746  func(update_no, xml);
747  }
748  else{
749  func(update_no, xml_out);
750  }
751  }
752 
753 
754  // Function call
755  //void
756  //InlineDiscoEigCG::func(unsigned long update_no,
757  // XMLWriter& xml_out)
758  void InlineMeas::func(unsigned long update_no,
759  XMLWriter& xml_out)
760  {
761  START_CODE();
762 
763  StopWatch snoop;
764  snoop.reset();
765  snoop.start();
766 
767  /*** Stuff to set up everything! ***/
768  // Test and grab a reference to the gauge field
769  XMLBufferWriter gauge_xml;
770  try
771  {
772  TheNamedObjMap::Instance().getData< multi1d<LatticeColorMatrix> >(params.named_obj.gauge_id);
773  TheNamedObjMap::Instance().get(params.named_obj.gauge_id).getRecordXML(gauge_xml);
774  }
775  catch( std::bad_cast )
776  {
777  QDPIO::cerr << InlineDiscoEigCGEnv::name << ": caught dynamic cast error"
778  << std::endl;
779  QDP_abort(1);
780  }
781  catch (const std::string& e)
782  {
783  QDPIO::cerr << name << ": std::map call failed: " << e
784  << std::endl;
785  QDP_abort(1);
786  }
787  const multi1d<LatticeColorMatrix>& u =
788  TheNamedObjMap::Instance().getData< multi1d<LatticeColorMatrix> >(params.named_obj.gauge_id);
789 
790  push(xml_out, "discoEigCG");
791  write(xml_out, "update_no", update_no);
792 
793  QDPIO::cout << name << ": Disconnected diagrams with eigCG vectors" << std::endl;
794 
795  proginfo(xml_out); // Print out basic program info
796 
797  // Write out the input
798  params.write(xml_out, "Input");
799 
800  // Write out the config info
801  write(xml_out, "Config_info", gauge_xml);
802 
803  push(xml_out, "Output_version");
804  write(xml_out, "out_version", 1);
805  pop(xml_out);
806 
807  // First calculate some gauge invariant observables just for info.
808  // This is really cheap.
809  MesPlq(xml_out, "Observables", u);
810 
811  // Save current seed
812  Seed ran_seed;
813  QDP::RNG::savern(ran_seed);
814 
815  //
816  // Read the source and solutions
817  //
818  StopWatch swatch;
819  swatch.reset();
820  swatch.start();
821 
822  int N_quarks = params.param.chi.size() ;
823 
824  multi1d< Handle< DilutionScheme<LatticeFermion> > > quarks(N_quarks);
825 
826  try{
827  // Loop over quark dilutions
828  for(int n(0); n < params.param.chi.size(); n++){
829  const GroupXML_t& dil_xml = params.param.chi[n];
830  std::istringstream xml_d(dil_xml.xml);
831  XMLReader diltop(xml_d);
832  QDPIO::cout << "Dilution type = " << dil_xml.id << std::endl;
833  quarks[n] =
834  TheFermDilutionSchemeFactory::Instance().createObject(dil_xml.id,
835  diltop,
836  dil_xml.path);
837  }
838  }
839  catch(const std::string& e){
840  QDPIO::cerr << name << ": Caught Exception constructing dilution scheme: " << e << std::endl;
841  QDP_abort(1);
842  }
843 
844 
845  //-------------------------------------------------------------------
846  //Sanity checks
847 
848  //Another Sanity check, the three quarks must all be
849  //inverted on the same cfg
850  for (int n = 1 ; n < N_quarks ; n++){
851  if (quarks[0]->getCfgInfo() != quarks[n]->getCfgInfo()){
852  QDPIO::cerr << name << " : Quarks do not contain the same cfg info";
853  QDPIO::cerr << ", quark "<< n << std::endl;
854  QDP_abort(1);
855  }
856  }
857 
858  //Also ensure that the cfg on which the inversions were performed
859  //is the same as the cfg that we are using
860  {
861  std::string cfgInfo;
862 
863  //Really ugly way of doing this (Robert Heeeelp!!)
864  XMLBufferWriter top;
865  write(top, "Config_info", gauge_xml);
866  XMLReader from(top);
867  XMLReader from2(from, "/Config_info");
868  std::ostringstream os;
869  from2.print(os);
870 
871  cfgInfo = os.str();
872 
873  if (cfgInfo != quarks[0]->getCfgInfo()){
874  QDPIO::cerr << name << " : Quarks do not contain the same";
875  QDPIO::cerr << " cfg info as the gauge field." ;
876  QDPIO::cerr << "gauge: XX"<<cfgInfo<<"XX quarks: XX" ;
877  QDPIO::cerr << quarks[0]->getCfgInfo()<<"XX"<< std::endl;
878  QDP_abort(1);
879  }
880  }
881 
882  int decay_dir = quarks[0]->getDecayDir();
883  //
884  // Initialize the slow Fourier transform phases
885  //
886  SftMom phases(params.param.p2_max, false, decay_dir);
887 
888  // Create even/odd subsets on each timeslice:
889  Set timerb;
890  timerb.make(TimeSliceRBFunc(decay_dir));
891 
892  // Another sanity check. The seeds of all the quarks must be different
893  // and thier decay directions must be the same
894  for(int n = 1 ; n < quarks.size(); n++){
895  if(toBool(quarks[n]->getSeed()==quarks[0]->getSeed())){
896  QDPIO::cerr << name << ": error, quark seeds are the same" << std::endl;
897  QDP_abort(1);
898  }
899 
900  if(toBool(quarks[n]->getDecayDir()!=quarks[0]->getDecayDir())){
901  QDPIO::cerr<<name<< ": error, quark decay dirs do not match" <<std::endl;
902  QDP_abort(1);
903  }
904  }
905 
906  // Instantiate the Dirac operator:
908 
909  //Now read evecs from disk, if file is specified.
910  multi1d<LatticeFermion> vec; // the vectors
911  CholeskyFactors Clsk; // the Cholesky Factors
912  if (params.named_obj.evecs_file!="")
914 
915  std::map< KeyOperator_t, ValOperator_t > data ;
916 
917  multi1d<multi1d< multi1d<LatticeFermion> > > quarkstilde(quarks.size());
918  for(int n(0);n<quarks.size();n++){
919  quarkstilde[n].resize(quarks[n]->getNumTimeSlices());
920  for (int it(0) ; it < quarks[n]->getNumTimeSlices() ; it++){
921  quarkstilde[n][it].resize(quarks[n]->getDilSize(it));
922  }
923  }
924 
925  /*** Everything is initialized, now to the real code ***/
926 
927  // chitilde = P_R S^-1 \eta_o
928  // If there is no evecs file, then PR = 1
929  if (params.named_obj.evecs_file!="")
930  PRchi(quarkstilde, quarks, Doo, Clsk, vec, params.param, u);
931  else
932  PRchi(quarkstilde, quarks);
933 
934  for(int n(0);n<quarks.size();n++){
935  for (int it(0) ; it < quarks[n]->getNumTimeSlices() ; it++){
936  int t = quarks[n]->getT0(it) ;
937  QDPIO::cout<<" Doing quark: "<< n <<std::endl ;
938  QDPIO::cout<<" quark: "<< n <<" has "<<quarks[n]->getDilSize(it);
939  QDPIO::cout<<" dilutions on time slice "<< t <<std::endl ;
940  for(int i = 0 ; i < quarks[n]->getDilSize(it) ; i++){
941  QDPIO::cout<<" Doing dilution : "<<i<<std::endl ;
942  multi1d<short int> d ;
943  // The q chosen should be from quarkstilde = PR*quarks->dilutedSolution()
944  LatticeFermion qbar = quarks[n]->dilutedSource(it,i);
945  LatticeFermion q = quarkstilde[n][it][i];
946  QDPIO::cout<<" Starting recursion "<<std::endl ;
947  // This is the noise std::vector piece.
948  do_disco(data, qbar, q, phases, t, d, params.param.max_path_length);
949 
950  QDPIO::cout<<" done with recursion! "
951  <<" The length of the path is: "<<d.size()<<std::endl ;
952  }
953  QDPIO::cout<<" Done with dilutions for quark: "<<n <<std::endl ;
954  }
955  }
956 
957  // Okay, first we are going to normalize all the pieces above by the number of
958  // quarks...
961  std::map< KeyOperator_t, ValOperator_t >::iterator it;
962 
963  for(it=data.begin();it!=data.end();it++){
964  key.key() = it->first ;
965  val.data().op.resize(it->second.op.size()) ;
966  for(int i(0);i<it->second.op.size();i++){
967  val.data().op[i] = it->second.op[i]/toDouble(quarks.size());
968  }
969  }
970 
971  // Now calculate the other pieces which need no normalization...
972  // Note using just timeslices for quarks[0]...may be a problem
973  // if quarks dilute on diff timeslices...
974 
975  if (params.named_obj.evecs_file!=""){// Only if we have vectors...
976  for (int it(0) ; it < quarks[0]->getNumTimeSlices() ; it++){
977  multi1d<short int> d ;
978  int t = quarks[0]->getT0(it) ;
979  QDPIO::cout<<" Starting recursion again"<<std::endl ;
980  // Part with deflation..
981  do_disco(data, Clsk, vec, params.param, Doo, u, t, timerb[2*t+1], phases,d);
982 
983  QDPIO::cout<<" done with recursion! "
984  <<" The length of the path is: "<<d.size()<<std::endl ;
985  }
986  }
987 
988  //After all the pieces are computed we write the final result to the database
989  // DB storage
990  BinaryStoreDB<SerialDBKey<KeyOperator_t>,SerialDBData<ValOperator_t> > qdp_db;
991 
992  // Open the file, and write the meta-data and the binary for this operator
993  {
994  XMLBufferWriter file_xml;
995 
996  push(file_xml, "DBMetaData");
997  write(file_xml, "id", std::string("discoEigElemOp"));
998  write(file_xml, "lattSize", QDP::Layout::lattSize());
999  write(file_xml, "decay_dir", decay_dir);
1000  write(file_xml, "Params", params.param);
1001  write(file_xml, "Config_info", gauge_xml);
1002  pop(file_xml);
1003 
1004  std::string file_str(file_xml.str());
1005  qdp_db.setMaxUserInfoLen(file_str.size());
1006 
1007  qdp_db.open(params.named_obj.op_db_file, O_RDWR | O_CREAT, 0664);
1008 
1009  qdp_db.insertUserdata(file_str);
1010  }
1011 
1012  // Store all the data
1013  for(it=data.begin();it!=data.end();it++){
1014  key.key() = it->first ;
1015  val.data().op.resize(it->second.op.size()) ;
1016  // DON'T normalize to number of quarks here, because we only do it on a
1017  // certain number of the terms in the trace...done above
1018  for(int i(0);i<it->second.op.size();i++)
1019  val.data().op[i] = it->second.op[i];
1020  qdp_db.insert(key,val) ;
1021  }
1022 
1023  // Close the namelist output file XMLDAT
1024  pop(xml_out); // DiscoEigCG
1025 
1026  snoop.stop();
1027  QDPIO::cout << name << ": total time = "
1028  << snoop.getTimeInSeconds()
1029  << " secs" << std::endl;
1030 
1031  QDPIO::cout << name << ": ran successfully" << std::endl;
1032 
1033  END_CODE();
1034  }
1035  } // namespace InlineDiscoEigCGEnv
1036 }// namespace chroma
Inline measurement factory.
Heavy Baryon (Qll) 2-pt function : Orginos and Savage.
Baryon spin and projector matrices.
All baryon operators.
Factory for producing baryon operators.
Even-odd preconditioned Clover-Dirac operator.
Even-odd preconditioned linear operator.
Definition: eoprec_linop.h:92
Even-odd preconditioned Wilson-Dirac operator.
Class for counted reference semantics.
Definition: handle.h:33
Inline measurement of stochastic baryon operators.
void operator()(const unsigned long update_no, XMLWriter &xml_out)
Do the measurement.
void func(const unsigned long update_no, XMLWriter &xml_out)
Do the measurement.
Serializable value harness.
Definition: key_val_db.h:69
D & data()
Setter.
Definition: key_val_db.h:78
Serializable key harness.
Definition: key_val_db.h:21
K & key()
Setter.
Definition: key_val_db.h:30
Fourier transform phase factor support.
Definition: sftmom.h:35
static T & Instance()
Definition: singleton.h:432
Parameters for Clover fermion action.
int mu
Definition: cool.cc:24
Random Z(N) source construction using dilution.
All dilution scheme factories.
Factory for dilution schemes.
Parallel transport a lattice field.
Even-odd const determinant Wilson-like fermact.
Fermion action factories.
All Wilson-type fermion actions.
void proginfo(XMLWriter &xml)
Print out basic information about this program.
Definition: proginfo.cc:24
std::string makeXMLFileName(std::string xml_file, unsigned long update_no)
Return a xml file name for inline measurements.
multi1d< GroupXML_t > readXMLArrayGroup(XMLReader &xml_in, const std::string &path, const std::string &type_name)
Read group and return as a std::string.
GroupXML_t readXMLGroup(XMLReader &xml_in, const std::string &path, const std::string &type_name)
Read group and return as a std::string.
Class for counted reference semantics.
Inline measurement of stochastic 3pt functions.
Key and values for DB.
unsigned j
Definition: ldumul_w.cc:35
unsigned n
Definition: ldumul_w.cc:36
Linear operators.
static int m[4]
Definition: make_seeds.cc:16
void savern(int iseed[4])
Definition: make_seeds.cc:46
Make xml file writer.
int it
Definition: meslate.cc:33
int t
Definition: meslate.cc:37
Nd
Definition: meslate.cc:74
Double q
Definition: mesq.cc:17
Named object function std::map.
static bool registered
Local registration flag.
bool operator<(const KeyOperator_t &a, const KeyOperator_t &b)
bool registerAll()
Register all the factories.
void PRchi(multi1d< multi1d< multi1d< LatticeFermion > > > &quarkstilde, const multi1d< Handle< DilutionScheme< LatticeFermion > > > &quarks, Handle< EvenOddPrecLinearOperator< T, P, Q > > &Doo, CholeskyFactors Clsk, multi1d< LatticeFermion > &vec, const Params::Param_t &param, const P &u)
multi1d< LatticeColorMatrix > P
void read(XMLReader &xml, const std::string &path, Params::Param_t &param)
void do_disco(std::map< KeyOperator_t, ValOperator_t > &db, const LatticeFermion &qbar, const LatticeFermion &q, const SftMom &p, const int &t, const multi1d< short int > &path, const int &max_path_length)
Handle< EvenOddPrecLinearOperator< T, P, Q > > createOddOdd_Op(const Params::Param_t &param, const P &u)
void write(XMLWriter &xml, const std::string &path, const Params::Param_t &param)
std::ostream & operator<<(std::ostream &os, const KeyOperator_t &d)
multi1d< LatticeColorMatrix > Q
void ReadOPTEigCGVecs(multi1d< LatticeFermion > &vec, CholeskyFactors &Clsk, const std::string &evecs_file)
QDPSubTypeTrait< typename BinaryReturn< C1, C2, FnLocalInnerProduct >::Type_t >::Type_t localInnerProduct(const QDPSubType< T1, C1 > &l, const QDPType< T2, C2 > &r)
const int N_quarks
Number of quarks to be used in this construction.
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
for(cb=0;cb< Ncb;++cb) cp+
Definition: pbg5p_w.cc:145
static multi1d< LatticeColorMatrix > u
push(xml_out,"Condensates")
int i
Definition: pbg5p_w.cc:55
@ MINUS
Definition: chromabase.h:45
@ PLUS
Definition: chromabase.h:45
Double cp
Definition: invbicg.cc:107
Complex a
Definition: invbicg.cc:95
pop(xml_out)
void MesPlq(const multi1d< LatticeColorMatrixF3 > &u, multi2d< Double > &plane_plaq, Double &link)
Definition: mesplq.cc:83
DComplex d
Definition: invbicg.cc:99
START_CODE()
Complex b
Definition: invbicg.cc:96
const WilsonTypeFermAct< multi1d< LatticeFermion > > Handle< const ConnectState > state
Definition: pbg5p_w.cc:28
static QOP_info_t info
Double zero
Definition: invbicg.cc:106
::std::string string
Definition: gtest.h:1979
#define FORWARD
Definition: primitives.h:82
#define BACKWARD
Definition: primitives.h:83
Print out basic info about this program.
Double sum
Definition: qtopcor.cc:37
All quark smearing constructors.
Factory for producing quark smearing objects.
Fourier transform phase factor support.
All make sink constructors.
Factory for producing quark prop sinks.
All source smearing.
Factory for producing quark smearing objects.
Params for clover ferm acts.
Hold group xml and type id.
struct Chroma::InlineDiscoEigCGEnv::Params::NamedObject_t named_obj
struct Chroma::InlineDiscoEigCGEnv::Params::Param_t param
void write(XMLWriter &xml_out, const std::string &path)
Params for wilson ferm acts.
multi1d< LatticeColorMatrix > U
Generate a unique id.
Wilson fermion action parameters.
Volume source of Z(N) noise.