CHROMA
teoprec_logdet_linop.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 /*! @file
3  * @brief Time-preconditioned Linear Operators
4  */
5 
6 #ifndef __teoprec_logdet_linop_h__
7 #define __teoprec_logdet_linop_h__
8 
9 #include "teoprec_linop.h"
10 
11 namespace Chroma
12 {
13 
14  //-----------------------------------------------------------------------------------
15  //! Even-odd and time preconditioned linear operator
16  /*! @ingroup linop
17  *
18  * Given a matrix M written in separate time and space operators
19  *
20  * M = D_t + D_s
21  *
22  * The time preconditioning consists of multiplying by the inverse
23  * of the time operator to give
24  *
25  * M' = 1 + D_t^(-1)*D_s
26  *
27  * For spatial even-odd precond., this interface requires the D_t to
28  * be diagonal in spatial components - have no space-space or space-time
29  * components. Hence, this means no even-odd component.
30  * Also, the D_s must no time coupling, and no even-even or odd-odd
31  * component - e.g. all diagonal terms have been pushed into D_t.
32  *
33  * Rewrite M' into block form:
34  *
35  * [ A D ]
36  * [ E,E E,O ]
37  * M' = [ ]
38  * [ D A ]
39  * [ O,E O,O ]
40  *
41  * where the E,O refer to only the spatial dimensions and
42  *
43  * A(e,e) = 1 + D_t^(-1)(e,e) * D_s(e,e) -> 1 # D_s(e,e)=0
44  * D(e,o) = D_t^(-1)(e,e) * D_s(e,o) # is a matrix in time-time
45  * D(o,e) = D_t^(-1)(o,o) * D_s(o,e) # is a matrix in time-time
46  * A(o,o) = 1 + D_t^(-1)(o,o) * D_s(o,o) -> 1 # D_s(o,o)=0
47  *
48  * A(e,e)^(-1) = <diagonal in space, matrix in time-time components>
49  *
50  * Spatial even-odd preconditioning consists of using the triangular matrices
51  *
52  * [ 1 0 ]
53  * [ E,E E,O ]
54  * L = [ ]
55  * [ D A^(-1) 1 ]
56  * [ O,E E,E O,O ]
57  *
58  * and
59  *
60  * [ A D ]
61  * [ E,E E,O ]
62  * U = [ ]
63  * [ 0 1 ]
64  * [ O,E O,O ]
65  *
66  * The preconditioned matrix is formed from
67  *
68  * ~
69  * M = L^-1 * M' * U^-1
70  *
71  * where
72  *
73  * [ 1 0 ]
74  * [ E,E E,O ]
75  * L^(-1) = [ ]
76  * [ - D A^(-1) 1 ]
77  * [ O,E E,E O,O ]
78  *
79  * and
80  *
81  * [ A^(-1) - A^(-1) D ]
82  * [ E,E E,E E,O ]
83  * U^(-1) = [ ]
84  * [ 0 1 ]
85  * [ O,E O,O ]
86  *
87  * Resulting in a new M
88  *
89  * [ 1 0 ]
90  * ~ [ E,E E,O ]
91  * M = [ ]
92  * [ 0 A - D A^(-1) D ]
93  * [ O,E O,O O,E E,E E,O ]
94  *
95  *
96  * This class is used to implement the resulting linear operator
97  *
98  * ~
99  * M = A(o,o) - D(o,e) * A^-1(e,e) * D(e,o)
100  * = 1 - D_t^(-1)(o,o) * D_s(o,e) * D_t^(-1)(e,e) * D_s(e,o)
101  *
102  * ~
103  * M^dag = 1 - D_s(o,e)^dag * D_t^(-1)(e,e)^dag * D_s(e,o)^dag * D_t^(-1)(o,o)^dag
104  *
105  * By construction, the linear operator is ONLY defined on the odd subset
106  *
107  * The non-symmetrical nature of the daggered version means the two
108  * cases (no-dagger and dagger) must be handled separately. This is
109  * in contrast to the standard (4D) even-odd precond. case where the
110  * the daggered version has the same structure, except the dagger
111  * is pushed down into the individual pieces.
112  *
113  * Here A^{-1}_{ee} does depend on the gauge fields but we can
114  * exactly simulate the determinant without pseudofermion fields
115  * since we know det A_{ee} and can write it in the action as
116  * exp( log det A ) = exp( Tr Ln A )
117  *
118  * Since we can explicitly evaluate Tr Ln A for the action, we
119  * can also evaluate the force contribution
120  *
121  * d/dt ( Tr Ln A ) = Tr ( (d/dt)A A^{-1} )
122  *
123  * and d/dt ( A^{-1} ) = A^{-1} [ (d/dt)A ] A^{-1}
124  *
125  * hence we have functions logDetEvenEvenLinOp()
126  * and derivEvenEvenLinOp()
127  * and derivLogDetEvenEvenLinOp()
128  */
129 
130  template<typename T, typename P, typename Q>
132  {
133  public:
134  //! Virtual destructor to help with cleanup;
136 
137  //! Only defined on the odd lattice
138  const Subset& subset() const {return rb[1];} // not correct, need space-rb
139 
140  //! Apply the derivative of the operator onto a source std::vector
141  /*! User should make sure deriv routines do a resize */
142  virtual void deriv(P& ds_u, const T& chi, const T& psi,
143  enum PlusMinus isign) const
144  {
145  // Need deriv of chi^dag*[psi + D_t^(-1)*D_s*psi]
146  enum PlusMinus msign = (isign == PLUS) ? MINUS : PLUS;
147 
148  //
149  // Make sure the deriv routines do a resize !!!
150  //
151  T tmp1; moveToFastMemoryHint(tmp1);
152  T tmp2; moveToFastMemoryHint(tmp2);
153  T tmp3; moveToFastMemoryHint(tmp3);
154  P ds_1; moveToFastMemoryHint(ds_1);
155 
156  switch (isign)
157  {
158  case PLUS:
159  // Need deriv of - chi^dag*(D_t^(-1)(o,o) * D_s(o,e) * D_t^(-1)(e,e) * D_s(e,o))*psi
160  //
161  // NOTE: even with even-odd decomposition, the ds_u will still have contributions
162  // on all cb. So, no adding of ds_1 onto ds_u under a subset
163  //
164  // ds_u = + chi^dag * Dtinv(o,o) * Dt'(o,o) * Dtinv(o,o)*D_s(o,e)*Dtinv(e,e)*D_s(e,o) * psi
165  evenOddSpaceLinOp(tmp1, psi, isign);
167  oddEvenSpaceLinOp(tmp1, tmp2, isign);
168  oddOddTimeInvLinOp(tmp3, chi, msign);
169  derivOddOddTimeLinOp(ds_u, tmp3, tmp1, isign);
170 
171  // ds_u -= chi^dag * Dtinv(o,o) * D'_s(o,e) *Dtinv(e,e)*D_s(e,o) * psi
172  evenOddSpaceLinOp(tmp1, psi, isign);
174  oddOddTimeInvLinOp(tmp3, chi, msign);
175  derivOddEvenTimeLinOp(ds_1, tmp3, tmp1, isign);
176  ds_u -= ds_1;
177 
178  // ds_u += chi^dag * Dtinv(o,o) * D_s(o,e) *Dtinv(e,e) * Dt'(e,e) * Dtinv(e,e)*D_s(e,o) * psi
180  evenEvenTimeInvLinOp(tmp1, tmp2, msign);
181  oddOddTimeInvLinOp(tmp3, chi, msign);
182  evenOddSpaceLinOp(tmp2, tmp3, msign);
183  evenEvenTimeInvLinOp(tmp3, tmp2, msign);
184  derivEvenEvenTimeLinOp(ds_1, tmp3, tmp1, isign);
185  ds_u += ds_1;
186 
187  // ds_u -= chi^dag * Dtinv(o,o) * D_s(o,e) *Dtinv(e,e) * D'_s(e,o) * psi
188  oddOddTimeInvLinOp(tmp3, chi, msign);
189  evenOddSpaceLinOp(tmp2, tmp3, msign);
190  evenEvenTimeInvLinOp(tmp3, tmp2, msign);
192  ds_u -= ds_1;
193  break;
194 
195  case MINUS:
196  // Need deriv of
197  // - chi^dag*(D_s(o,e)^dag * D_t^(-1)(e,e)^dag * D_s(e,o)^dag * D_t^(-1)(o,o)^dag)*psi
198  //
199  // ds_u = chi^dag*D_s(o,e)^dag* Dtinv(e,e)^dag * Dt'(e,e)^dag *Dtinv(e,e)^dag*D_s(e,o)^dag*Dtinv(o,o)^dag*psi
200  oddOddTimeInvLinOp(tmp1, psi, isign);
201  evenOddSpaceLinOp(tmp2, tmp1, isign);
203  evenOddSpaceLinOp(tmp2, chi, msign);
204  evenEvenTimeInvLinOp(tmp3, tmp2, msign);
205  derivEvenEvenTimeLinOp(ds_u, tmp3, tmp1, isign);
206 
207  // ds_u -= chi^dag * D'_s(o,e)^dag * Dtinv(e,e)^dag*D_s(e,o)^dag*Dtinv(o,o)^dag*psi
208  oddOddTimeInvLinOp(tmp1, psi, isign);
209  evenOddSpaceLinOp(tmp2, tmp1, isign);
211  derivOddEvenTimeLinOp(ds_1, chi, tmp1, isign);
212  ds_u -= ds_1;
213 
214  // ds_u += chi^dag*D_s(o,e)^dag*Dtinv(e,e)^dag*D_s(e,o)^dag*Dtinv(o,o)^dag * Dt'(o,o)^dag *Dtinv(o,o)^dag*psi
215  oddOddTimeInvLinOp(tmp1, psi, isign);
216  evenOddSpaceLinOp(tmp2, chi, msign);
217  evenEvenTimeInvLinOp(tmp3, tmp2, msign);
218  oddEvenSpaceLinOp(tmp2, tmp3, msign);
219  oddOddTimeInvLinOp(tmp3, tmp2, msign);
220  derivOddOddTimeLinOp(ds_1, tmp3, tmp1, isign);
221  ds_u += ds_1;
222 
223  // ds_u -= chi^dag*D_s(o,e)^dag* Dtinv(e,e)^dag *D'_s(e,o)^dag*Dtinv(o,o)^dag*psi
224  oddOddTimeInvLinOp(tmp1, psi, isign);
225  evenOddSpaceLinOp(tmp2, chi, msign);
226  evenEvenTimeInvLinOp(tmp3, tmp2, msign);
227  derivEvenOddTimeLinOp(ds_1, tmp3, tmp1, isign);
228  ds_u -= ds_1;
229  break;
230 
231  default:
232  QDPIO::cerr << "unknown sign" << std::endl;
233  QDP_abort(1);
234  }
235  }
236 
237  //! Apply the even-even block onto a source std::vector
238  virtual void derivEvenEvenTimeLinOp(P& ds_u, const T& chi, const T& psi,
239  enum PlusMinus isign) const
240  {
241  QDPIO::cerr << "EvenEvenTime: not implemented" << std::endl;
242  QDP_abort(1);
243  }
244 
245  //! Apply the the even-odd block onto a source std::vector
246  virtual void derivEvenOddSpaceLinOp(P& ds_u, const T& chi, const T& psi,
247  enum PlusMinus isign) const
248  {
249  QDPIO::cerr << "EvenOddSpace: not implemented" << std::endl;
250  QDP_abort(1);
251  }
252 
253  //! Apply the the odd-even block onto a source std::vector
254  virtual void derivOddEvenSpaceLinOp(P& ds_u, const T& chi, const T& psi,
255  enum PlusMinus isign) const
256  {
257  QDPIO::cerr << "EvenOddSpace: not implemented" << std::endl;
258  QDP_abort(1);
259  }
260 
261  //! Apply the the odd-odd block onto a source std::vector
262  virtual void derivOddOddTimeLinOp(P& ds_u, const T& chi, const T& psi,
263  enum PlusMinus isign) const
264  {
265  QDPIO::cerr << "OddOddTime: not implemented" << std::endl;
266  QDP_abort(1);
267  }
268  };
269 
270 
271 }
272 
273 
274 
275 #endif
Even-odd and time preconditioned linear operator.
virtual void evenOddSpaceLinOp(T &chi, const T &psi, enum PlusMinus isign) const =0
Apply the the even-odd block onto a source std::vector.
virtual void oddEvenSpaceLinOp(T &chi, const T &psi, enum PlusMinus isign) const =0
Apply the the odd-even block onto a source std::vector.
virtual void evenEvenTimeInvLinOp(T &chi, const T &psi, enum PlusMinus isign) const =0
Apply the inverse of the even-even block onto a source std::vector.
Even-odd and time preconditioned linear operator.
const Subset & subset() const
Only defined on the odd lattice.
virtual ~EvenOddTimePrecLogDetLinearOperator()
Virtual destructor to help with cleanup;.
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 derivOddOddTimeLinOp(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 derivOddEvenSpaceLinOp(P &ds_u, const T &chi, const T &psi, enum PlusMinus isign) const
Apply the the odd-even block onto a source std::vector.
virtual void derivEvenOddSpaceLinOp(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 void derivEvenEvenTimeLinOp(P &ds_u, const T &chi, const T &psi, enum PlusMinus isign) const
Apply the even-even block onto a source std::vector.
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
multi1d< LatticeFermion > chi(Ncb)
LatticeFermion psi
Definition: mespbg5p_w.cc:35
multi1d< LatticeColorMatrix > P
Definition: t_clover.cc:13
Even-odd Time-preconditioned Linear Operators.