CHROMA
eoprec_logdet_linop.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 /*! @file
3  * @brief Preconditioned Linear Operators where the Even Even part depends on the gauge field.
4  *
5  * We assume we can evaluate Log Det E, where E is the Even Even part.
6  * Essentially this is for things like clover.
7  */
8 
9 #ifndef __eoprec_logdet_linop_h__
10 #define __eoprec_logdet_linop_h__
11 
12 #include "eoprec_linop.h"
13 
14 using namespace QDP::Hints;
15 
16 namespace Chroma
17 {
18 
19  //-------------------------------------------------------------------------
20  //! Even-odd preconditioned linear operator
21  /*! @ingroup linop
22  *
23  * Support for even-odd preconditioned linear operators
24  * Given a matrix M written in block form:
25  *
26  * [ A D ]
27  * [ E,E E,O ]
28  * [ ]
29  * [ D A ]
30  * [ O,E O,O ]
31  *
32  * The preconditioning consists of using the triangular matrices
33  *
34  * [ 1 0 ]
35  * [ E,E E,O ]
36  * L = [ ]
37  * [ D A^(-1) 1 ]
38  * [ O,E E,E O,O ]
39  *
40  * and
41  *
42  * [ 1 A^{-1} D ]
43  * [ E,E EE E,O ]
44  * U = [ ]
45  * [ 0 1 ]
46  * [ O,E O,O ]
47  *
48  * The preconditioned matrix is formed from
49  *
50  * M' = L^-1 * M * U^-1
51  *
52  * where
53  *
54  * [ 1 0 ]
55  * [ E,E E,O ]
56  * L^(-1) = [ ]
57  * [ - D A^(-1) 1 ]
58  * [ O,E E,E O,O ]
59  *
60  * and
61  *
62  * [ 1 - A^(-1) D ]
63  * [ E,E E,E E,O ]
64  * U^(-1) = [ ]
65  * [ 0 1 ]
66  * [ O,E O,O ]
67  *
68  * Resulting in a new M
69  *
70  * [ A 0 ]
71  * [ E,E E,O ]
72  * [ ]
73  * [ 0 A - D A^(-1) D ]
74  * [ O,E O,O O,E E,E E,O ]
75  *
76  *
77  * This class is used to implement the resulting linear operator
78  *
79  * ~
80  * M = A(o,o) - D(o,e) . A^-1(e,e) . D(e,o)
81  *
82  * where A^{-1}_{ee} does depend on the gauge fields but we can
83  * exactly simulate the determinant without pseudofermion fields
84  * since we know det A_{ee} and can write it in the action as
85  * exp( log det A ) = exp( Tr Ln A )
86  *
87  * Since we can explicitly evaluate Tr Ln A for the action, we
88  * can also evaluate the force contribution
89  *
90  * d/dt ( Tr Ln A ) = Tr ( (d/dt)A A^{-1} )
91  *
92  * and d/dt ( A^{-1} ) = A^{-1} [ (d/dt)A ] A^{-1}
93  *
94  * hence we have functions logDetEvenEvenLinOp()
95  * and derivEvenEvenLinOp()
96  * and derivLogDetEvenEvenLinOp()
97  */
98 
99  template<typename T, typename P, typename Q>
101  {
102  public:
103  //! Virtual destructor to help with cleanup;
105 
106  //! Only defined on the odd lattice
107  const Subset& subset() const {return rb[1];}
108 
109  //! Return the fermion BC object for this linear operator
110  virtual const FermBC<T,P,Q>& getFermBC() const = 0;
111 
112  //! Apply the derivative of the operator onto a source std::vector
113  /*! User should make sure deriv routines do a resize */
114  virtual void deriv(P& ds_u, const T& chi, const T& psi,
115  enum PlusMinus isign) const
116  {
117  // Need deriv of (A_oo - D_oe*Ainv_ee*D_eo*psi_e)
118  enum PlusMinus msign = (isign == PLUS) ? MINUS : PLUS;
119 
120  //
121  // Make sure the deriv routines do a resize !!!
122  //
123  T tmp1, tmp2, tmp3; // if an array is used here, the space is not reserved
124  moveToFastMemoryHint(tmp1);
125  moveToFastMemoryHint(tmp2);
126  moveToFastMemoryHint(tmp3);
127 
128  P ds_1; // deriv routines should resize
129 
130  //
131  // NOTE: even with even-odd decomposition, the ds_u will still have contributions
132  // on all cb. So, no adding of ds_1 onto ds_u under a subset
133  //
134  // ds_u = chi^dag * A'_oo * psi
135  this->derivOddOddLinOp(ds_u, chi, psi, isign);
136 
137  // ds_u -= chi^dag * D'_oe * Ainv_ee * D_eo * psi_o
138  this->evenOddLinOp(tmp1, psi, isign);
139  this->evenEvenInvLinOp(tmp2, tmp1, isign);
140  this->derivOddEvenLinOp(ds_1, chi, tmp2, isign);
141  ds_u -= ds_1;
142 
143  // ds_u += chi^dag * D_oe * Ainv_ee * A'_ee * Ainv_ee * D_eo * psi_o
144 
145  // Reuse tmp2 = Ainv_ee D_eo psi_o
146  this->evenOddLinOp(tmp1, chi, msign);
147  this->evenEvenInvLinOp(tmp3, tmp1, msign);
148  this->derivEvenEvenLinOp(ds_1, tmp3, tmp2, isign);
149  ds_u += ds_1;
150 
151  // ds_u -= chi^dag * D_oe * Ainv_ee * D'_eo * psi_o
152  // Reuse tmp3^dag = chi^\dag D_oe Ainv_ee
153  this->derivEvenOddLinOp(ds_1, tmp3, psi, isign);
154  ds_u -= ds_1;
155 
156  getFermBC().zero(ds_u);
157  }
158 
159  //! Apply the derivative of the operator onto a source std::vector
160  /*! User should make sure deriv routines do a resize */
161  virtual void derivMultipole(P& ds_u, const multi1d<T>& chi, const multi1d<T>& psi,
162  enum PlusMinus isign) const
163  {
164  // Need deriv of (A_oo - D_oe*Ainv_ee*D_eo*psi_e)
165  enum PlusMinus msign = (isign == PLUS) ? MINUS : PLUS;
166 
167  //
168  // Make sure the deriv routines do a resize !!!
169  //
170  T tmp1;
171  multi1d<T> tmp2(chi.size());
172  multi1d<T> tmp3(chi.size()); // if an array is used here, the space is not reserved
173 
174  P ds_1; // deriv routines should resize
175 
176  //
177  // NOTE: even with even-odd decomposition, the ds_u will still have contributions
178  // on all cb. So, no adding of ds_1 onto ds_u under a subset
179  //
180  // ds_u = chi^dag * A'_oo * psi
181  this->derivOddOddLinOpMP(ds_u, chi, psi, isign);
182 
183  // ds_u -= chi^dag * D'_oe * Ainv_ee * D_eo * psi_o
184  for(int i=0; i < chi.size(); i++) {
185  this->evenOddLinOp(tmp1, psi[i], isign);
186  this->evenEvenInvLinOp(tmp2[i], tmp1, isign);
187  }
188  this->derivOddEvenLinOpMP(ds_1, chi, tmp2, isign);
189  ds_u -= ds_1;
190 
191 
192  // ds_u += chi^dag * D_oe * Ainv_ee * A'_ee * Ainv_ee * D_eo * psi_o
193  for(int i=0; i < chi.size(); i++) {
194  // Reuse tmp2 = Ainv_ee D_eo psi_o
195  this->evenOddLinOp(tmp1, chi[i], msign);
196  this->evenEvenInvLinOp(tmp3[i], tmp1, msign);
197  }
198  this->derivEvenEvenLinOpMP(ds_1, tmp3, tmp2, isign);
199  ds_u += ds_1;
200 
201  // ds_u -= chi^dag * D_oe * Ainv_ee * D'_eo * psi_o
202  // Reuse tmp3^dag = chi^\dag D_oe Ainv_ee
203  this->derivEvenOddLinOpMP(ds_1, tmp3, psi, isign);
204  ds_u -= ds_1;
205 
206  getFermBC().zero(ds_u);
207  }
208 
209  //! Apply the even-even block onto a source std::vector
210  virtual void derivEvenEvenLinOp(P& ds_u, const T& chi, const T& psi,
211  enum PlusMinus isign) const
212  {
213  QDPIO::cerr << "EvenOdd: not implemented" << std::endl;
214  QDP_abort(1);
215  }
216 
217  //! Apply the the even-odd block onto a source std::vector
218  virtual void derivEvenOddLinOp(P& ds_u, const T& chi, const T& psi,
219  enum PlusMinus isign) const
220  {
221  QDPIO::cerr << "EvenOdd: not implemented" << std::endl;
222  QDP_abort(1);
223  }
224 
225  //! Apply the the odd-even block onto a source std::vector
226  virtual void derivOddEvenLinOp(P& ds_u, const T& chi, const T& psi,
227  enum PlusMinus isign) const
228  {
229  QDPIO::cerr << "EvenOdd: not implemented" << std::endl;
230  QDP_abort(1);
231  }
232 
233  //! Apply the the odd-odd block onto a source std::vector
234  virtual void derivOddOddLinOp(P& ds_u, const T& chi, const T& psi,
235  enum PlusMinus isign) const
236  {
237  QDPIO::cerr << "EvenOdd: not implemented" << std::endl;
238  QDP_abort(1);
239  }
240 
241 
242  // Multipole derivatives
243  virtual void derivEvenEvenLinOpMP(P& ds_u, const multi1d<T>& chi, const multi1d<T>& psi,
244  enum PlusMinus isign) const
245  {
246  ds_u.resize(Nd);
247  ds_u = zero;
248 
249  P F_tmp; // deriv will resize
250  for(int i=0; i < chi.size(); i++) {
251  this->derivEvenEvenLinOp(F_tmp, chi[i], psi[i], isign);
252  ds_u += F_tmp;
253  }
254  }
255 
256  // Multipole derivatives
257  virtual void derivEvenOddLinOpMP(P& ds_u, const multi1d<T>& chi, const multi1d<T>& psi,
258  enum PlusMinus isign) const
259  {
260  // implement in terms existing derivatives:
261  ds_u.resize(Nd);
262  ds_u = zero;
263 
264  P F_tmp; // deriv will resize
265  for(int i=0; i < chi.size(); i++) {
266  this->derivEvenOddLinOp(F_tmp, chi[i], psi[i], isign);
267  ds_u += F_tmp;
268  }
269  }
270 
271  virtual void derivOddEvenLinOpMP(P& ds_u, const multi1d<T>& chi, const multi1d<T>& psi,
272  enum PlusMinus isign) const
273  {
274  // implement in terms existing derivatives:
275  ds_u.resize(Nd);
276  ds_u = zero;
277 
278  P F_tmp; // deriv will resize
279  for(int i=0; i < chi.size(); i++) {
280  this->derivOddEvenLinOp(F_tmp, chi[i], psi[i], isign);
281  ds_u += F_tmp;
282  }
283  }
284 
285  virtual void derivOddOddLinOpMP(P& ds_u, const multi1d<T>& chi, const multi1d<T>& psi,
286  enum PlusMinus isign) const
287  {
288  // Trivially zero since we are constdet?
289  ds_u.resize(Nd);
290  ds_u = zero;
291 
292  P F_tmp;
293  for(int i=0; i < chi.size(); i++) {
294  this->derivOddOddLinOp(F_tmp, chi[i], psi[i], isign);
295  ds_u += F_tmp;
296  }
297  }
298 
299  //! Get the force from the EvenEven Trace Log
300  virtual void derivLogDetEvenEvenLinOp(P& ds_u, enum PlusMinus isign) const
301  {
302  QDPIO::cerr << "EvenOdd: not implemented" << std::endl;
303  QDP_abort(1);
304  }
305 
306  //! Get the log det of the even even part
307  virtual Double logDetEvenEvenLinOp(void) const = 0;
308  };
309 
310 
311  //-------------------------------------------------------------------------
312  //! Even-odd preconditioned 5D linear operator
313  /*! @ingroup linop
314  *
315  * Support for even-odd preconditioned linear operators
316  * Given a matrix M written in block form:
317  *
318  * [ A D ]
319  * [ E,E E,O ]
320  * [ ]
321  * [ D A ]
322  * [ O,E O,O ]
323  *
324  * The preconditioning consists of using the triangular matrices
325  *
326  * [ 1 0 ]
327  * [ E,E E,O ]
328  * L = [ ]
329  * [ D A^(-1) 1 ]
330  * [ O,E E,E O,O ]
331  *
332  * and
333  *
334  * [ 1 A^{-1} D ]
335  * [ E,E EE E,O ]
336  * U = [ ]
337  * [ 0 1 ]
338  * [ O,E O,O ]
339  *
340  * The preconditioned matrix is formed from
341  *
342  * M' = L^-1 * M * U^-1
343  *
344  * where
345  *
346  * [ 1 0 ]
347  * [ E,E E,O ]
348  * L^(-1) = [ ]
349  * [ - D A^(-1) 1 ]
350  * [ O,E E,E O,O ]
351  *
352  * and
353  *
354  * [ 1 - A^(-1) D ]
355  * [ E,E E,E E,O ]
356  * U^(-1) = [ ]
357  * [ 0 1 ]
358  * [ O,E O,O ]
359  *
360  * Resulting in a new M
361  *
362  * [ A 0 ]
363  * [ E,E E,O ]
364  * [ ]
365  * [ 0 A - D A^(-1) D ]
366  * [ O,E O,O O,E E,E E,O ]
367  *
368  *
369  * This class is used to implement the resulting linear operator
370  *
371  * ~
372  * M = A(o,o) - D(o,e) . A^-1(e,e) . D(e,o)
373  *
374  * where A^{-1}_{ee} does depend on the gauge fields but we can
375  * exactly simulate the determinant without pseudofermion fields
376  * since we know det A_{ee} and can write it in the action as
377  * exp( log det A ) = exp( Tr Ln A )
378  *
379  * Since we can explicitly evaluate Tr Ln A for the action, we
380  * can also evaluate the force contribution
381  *
382  * d/dt ( Tr Ln A ) = Tr ( (d/dt)A A^{-1} )
383  *
384  * and d/dt ( A^{-1} ) = A^{-1} [ (d/dt)A ] A^{-1}
385  *
386  * hence we have functions lnDetEvenEven()
387  * and derivEvenEven()
388  * and derivEvenEvenInv()
389  * --- this needs work, may not even need more than lnDetEvenEven
390  *
391  *
392  */
393 
394  template<typename T, typename P, typename Q>
396  {
397  public:
398  //! Virtual destructor to help with cleanup;
400 
401  //! Only defined on the odd lattice
402  const Subset& subset() const {return rb[1];}
403 
404  //! Get the szie expected of arrays
405  virtual int size() const = 0;
406 
407  //! Return the fermion BC object for this linear operator
408  virtual const FermBC<T,P,Q>& getFermBC() const = 0;
409 
410  //! Apply the operator onto a source std::vector
411  /*! User should make sure deriv routines do a resize */
412  virtual void deriv(P& ds_u, const multi1d<T>& chi, const multi1d<T>& psi,
413  enum PlusMinus isign) const
414  {
415  // Need deriv of (A_oo - D_oe*Ainv_ee*D_eo*psi_e)
416  enum PlusMinus msign = (isign == PLUS) ? MINUS : PLUS;
417 
418  //
419  // Make sure the deriv routines do a resize !!!
420  //
421  multi1d<T> tmp1(size()), tmp2(size()), tmp3(size()); // if an array is used here, the space is not reserved
422  moveToFastMemoryHint(tmp1);
423  moveToFastMemoryHint(tmp2);
424  moveToFastMemoryHint(tmp3);
425 
426  P ds_1; // deriv routines should resize
427 
428  //
429  // NOTE: even with even-odd decomposition, the ds_u will still have contributions
430  // on all cb. So, no adding of ds_1 onto ds_u under a subset
431  //
432  // ds_u = chi^dag * A'_oo * psi
433  this->derivOddOddLinOp(ds_u, chi, psi, isign);
434 
435  // ds_u -= chi^dag * D'_oe * Ainv_ee * D_eo * psi_o
436  this->evenOddLinOp(tmp1, psi, isign);
437  this->evenEvenInvLinOp(tmp2, tmp1, isign);
438  this->derivOddEvenLinOp(ds_1, chi, tmp2, isign);
439  ds_u -= ds_1;
440 
441  // ds_u += chi^dag * D_oe * Ainv_ee * A'_ee * Ainv_ee * D_eo * psi_o
442  this->evenOddLinOp(tmp1, psi, isign);
443  this->evenEvenInvLinOp(tmp2, tmp1, isign);
444  this->evenOddLinOp(tmp1, chi, msign);
445  this->evenEvenInvLinOp(tmp3, tmp1, msign);
446  this->derivEvenEvenLinOp(ds_1, tmp3, tmp2, isign);
447  ds_u += ds_1;
448 
449  // ds_u -= chi^dag * D_oe * Ainv_ee * D'_eo * psi_o
450  this->evenOddLinOp(tmp1, chi, msign);
451  this->evenEvenInvLinOp(tmp3, tmp1, msign);
452  this->derivEvenOddLinOp(ds_1, tmp3, psi, isign);
453  ds_u -= ds_1;
454 
455  getFermBC().zero(ds_u);
456  }
457 
458  //! Apply the even-even block onto a source std::vector
459  virtual void derivEvenEvenLinOp(P& ds_u, const multi1d<T>& chi, const multi1d<T>& psi,
460  enum PlusMinus isign) const
461  {
462  QDPIO::cerr << "EvenOdd: not implemented" << std::endl;
463  QDP_abort(1);
464  }
465 
466  //! Apply the the even-odd block onto a source std::vector
467  virtual void derivEvenOddLinOp(P& ds_u, const multi1d<T>& chi, const multi1d<T>& psi,
468  enum PlusMinus isign) const
469  {
470  QDPIO::cerr << "EvenOdd: not implemented" << std::endl;
471  QDP_abort(1);
472  }
473 
474  //! Apply the the odd-even block onto a source std::vector
475  virtual void derivOddEvenLinOp(P& ds_u, const multi1d<T>& chi, const multi1d<T>& psi,
476  enum PlusMinus isign) const
477  {
478  QDPIO::cerr << "EvenOdd: not implemented" << std::endl;
479  QDP_abort(1);
480  }
481 
482  //! Apply the the odd-odd block onto a source std::vector
483  virtual void derivOddOddLinOp(P& ds_u, const multi1d<T>& chi, const multi1d<T>& psi,
484  enum PlusMinus isign) const
485  {
486  QDPIO::cerr << "EvenOdd: not implemented" << std::endl;
487  QDP_abort(1);
488  }
489 
490  //! Get the force from the EvenEven Trace Log
491  virtual void derivLogDetEvenEvenLinOp(P& ds_u, enum PlusMinus isign) const
492  {
493  QDPIO::cerr << "EvenOdd: not implemented" << std::endl;
494  QDP_abort(1);
495  }
496 
497  //! Get the log det of the even even part
498  virtual Double logDetEvenEvenLinOp(void) const = 0;
499  };
500 
501 
502 
503 }
504 #endif
Even-odd preconditioned linear operator including derivatives for arrays.
Definition: eoprec_linop.h:312
Even-odd preconditioned linear operator.
Definition: eoprec_linop.h:92
Even-odd preconditioned 5D linear operator.
const Subset & subset() const
Only defined on the odd lattice.
virtual ~EvenOddPrecLogDetLinearOperatorArray()
Virtual destructor to help with cleanup;.
virtual void derivEvenOddLinOp(P &ds_u, const multi1d< T > &chi, const multi1d< T > &psi, enum PlusMinus isign) const
Apply the the even-odd block onto a source std::vector.
virtual int size() const =0
Get the szie expected of arrays.
virtual void derivLogDetEvenEvenLinOp(P &ds_u, enum PlusMinus isign) const
Get the force from the EvenEven Trace Log.
virtual void deriv(P &ds_u, const multi1d< T > &chi, const multi1d< T > &psi, enum PlusMinus isign) const
Apply the operator onto a source std::vector.
virtual const FermBC< T, P, Q > & getFermBC() const =0
Return the fermion BC object for this linear operator.
virtual void derivEvenEvenLinOp(P &ds_u, const multi1d< T > &chi, const multi1d< T > &psi, enum PlusMinus isign) const
Apply the even-even block onto a source std::vector.
virtual void derivOddOddLinOp(P &ds_u, const multi1d< T > &chi, const multi1d< T > &psi, enum PlusMinus isign) const
Apply the the odd-odd block onto a source std::vector.
virtual Double logDetEvenEvenLinOp(void) const =0
Get the log det of the even even part.
virtual void derivOddEvenLinOp(P &ds_u, const multi1d< T > &chi, const multi1d< T > &psi, enum PlusMinus isign) const
Apply the the odd-even block onto a source std::vector.
Even-odd preconditioned linear operator.
virtual void derivEvenOddLinOp(P &ds_u, const T &chi, const T &psi, enum PlusMinus isign) const
Apply the the even-odd block onto a source std::vector.
virtual ~EvenOddPrecLogDetLinearOperator()
Virtual destructor to help with cleanup;.
virtual void derivEvenOddLinOpMP(P &ds_u, const multi1d< T > &chi, const multi1d< T > &psi, enum PlusMinus isign) const
virtual void derivEvenEvenLinOp(P &ds_u, const T &chi, const T &psi, enum PlusMinus isign) const
Apply the even-even block onto a source std::vector.
virtual void derivLogDetEvenEvenLinOp(P &ds_u, enum PlusMinus isign) const
Get the force from the EvenEven Trace Log.
virtual Double logDetEvenEvenLinOp(void) const =0
Get the log det of the even even part.
virtual void derivEvenEvenLinOpMP(P &ds_u, const multi1d< T > &chi, const multi1d< T > &psi, enum PlusMinus isign) const
virtual const FermBC< T, P, Q > & getFermBC() const =0
Return the fermion BC object for this linear operator.
virtual void deriv(P &ds_u, const T &chi, const T &psi, enum PlusMinus isign) const
Apply the derivative of the operator onto a source std::vector.
virtual void derivOddOddLinOp(P &ds_u, const T &chi, const T &psi, enum PlusMinus isign) const
Apply the the odd-odd block onto a source std::vector.
virtual void derivOddOddLinOpMP(P &ds_u, const multi1d< T > &chi, const multi1d< T > &psi, enum PlusMinus isign) const
virtual void derivOddEvenLinOpMP(P &ds_u, const multi1d< T > &chi, const multi1d< T > &psi, enum PlusMinus isign) const
virtual void derivMultipole(P &ds_u, const multi1d< T > &chi, const multi1d< T > &psi, enum PlusMinus isign) const
Apply the derivative of the operator onto a source std::vector.
virtual void derivOddEvenLinOp(P &ds_u, const T &chi, const T &psi, enum PlusMinus isign) const
Apply the the odd-even block onto a source std::vector.
const Subset & subset() const
Only defined on the odd lattice.
Base class for all fermion action boundary conditions.
Definition: fermbc.h:20
Base class for even-odd preconditioned 4D and 5D Linop.
unsigned i
Definition: ldumul_w.cc:34
Nd
Definition: meslate.cc:74
Double tmp2
Definition: mesq.cc:30
Double tmp3
Definition: mesq.cc:31
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
LinOpSysSolverMGProtoClover::T T
@ MINUS
Definition: chromabase.h:45
@ PLUS
Definition: chromabase.h:45
Double zero
Definition: invbicg.cc:106
FloatingPoint< double > Double
Definition: gtest.h:7351
chi
Definition: pade_trln_w.cc:24
psi
Definition: pade_trln_w.cc:191
multi1d< LatticeColorMatrix > P
Definition: t_clover.cc:13